2011-09-30 4 views
0

이렇게 예상대로 작동하는 것이 좋습니다. JSON 요청에서 데이터를 가져온 다음 매핑 플러그인을 사용하여 매핑합니다. 클릭 바인딩에서 중첩 배열에 새 값을 추가하고 싶습니다.knockout.mapping plugin 및 knockoutjs로 만든 중첩 된 관측 가능 배열에 새 값 추가

바로 지금 내 코드에서 addPoint가 정의되지 않았다는 오류가 발생합니다.

보기 :

<table> 
    <tbody data-bind='template: {name: "statRowTemplate", foreach: stats }'></tbody> 
</table> 

<script id="statRowTemplate" type="text/html"> 
    {{if type() != "column"}} 
    <tr> 
      <td><label>Name: </label><input data-bind="value: name" /></td> 
      <td> 
        <label>Plot Points: </label><ul class="list-plot-points" data-bind="template: {name: 'dataTemplate' , foreach: data}"></ul> 
        <button data-bind="click: addPoint">Add Point</button> 
       </td> 

    </tr> 
    {{/if}} 
</script> 
<script type="text/html" id="dataTemplate">   
<li> 
     <input data-bind="value: val" /> 
</li> 
</script> 

<button data-bind="click: saveChanges">Save Changes</button> 

보기 모델

var viewModel = {}; 

$.getJSON('data-forecast-accuracy.json', function(result) { 

    function mappedData(data) { 
     this.val = data; 
    } 

    //override toJSON to turn it back into a single val 
    mappedData.prototype.toJSON = function() { 
     return parseInt(ko.utils.unwrapObservable(this.val), 10); //parseInt if you want or not 
    }; 

    var mapping = { 
     'data': { 
      create: function(options) { 
      return new mappedData(options.data) 
      } 
     } 
    } 

    viewModel.stats = ko.mapping.fromJS(result, mapping); 

    viewModel.addPoint = function() { 
    this.stats.data.push(new mappedData(0)); 
    } 

    viewModel.saveChanges = function() { 

     var unmapped = ko.mapping.toJSON(viewModel.stats); 
     //console.log(unmapped); 
     $.post('save-changes.php', {data: unmapped}) 
     .success(function(results) { console.log("success")}) 
     .error(function() { console.log("error"); }) 
     .complete(function() { console.log("complete"); }); 
    } 

    ko.applyBindings(viewModel); 
}); 

json으로 :

[{"type":"spline","marker":{"symbol":"diamond"},"name":"Cumulative","data":[10,17,18,18,16,17,18,19]},{"type":"spline","marker":{"symbol":"circle"},"name":"Monthly","data":[10,22,20,19,8,20,25,23]}]

나는에 포인트를 추가하기 위해 이전 응답에서이 jsfiddle을 조정 할 수 있었다 단일 배열. 생성 된 매핑을 통해이를 구현하는 방법을 찾아야합니다. 당신이보기 모델의 하위 속성에 대한 템플릿 안에이기 때문에

http://jsfiddle.net/vv2Wx/1/

답변

1

addPoint에 바인딩하는 경우 컨텍스트는보기 모델이 아닌 stats의 항목입니다.

viewModel에 전역 범위가있는 경우 click: viewModel.addPoint을 사용할 수 있습니다. addPoint 메서드에서 this이 올바르게 설정되어 있는지 확인해야합니다. 전역이없는

viewModel.addPoint = function() { 
    this.stats.data.push(new mappedData(0)); 
}.bind(viewModel); 

viewModel 경우에, 당신은 templateOptions를 통해 그것을에 전달할 수있는 가장 쉬운 방법은 같이 당신의 ViewModel 변수에 방법을 결합하는 것입니다.

다음
<tbody data-bind='template: {name: "statRowTemplate", 
          foreach: stats, templateOptions: { add: addPoints } }'></tbody> 

, 그것은 전화 같은 :처럼이 될 것입니다 당신이 KO 1.3 beta를 사용하는 경우, <button data-bind="click: $item.add">Add Point</button>

을 마지막으로, 당신은 할 수 있습니다 : <button data-bind="click: $root.addPoint">Add Point</button>

+0

나는 두 가지를 시도하고 내가 무엇입니까 error'Uncaught TypeError : undefined의 'push'메소드를 호출 할 수 없습니다. 새로운 배열을 각 배열에 독립적으로 추가 할 수 있기를 원했기 때문에 통계 템플릿에 버튼을 두었습니다. –

+1

OK- 실제로 addPoint 메소드가'stats'의 특정 항목을 다루길 원합니다. 'stats'에 대한 매핑을 추가하고 거기에 addPoint 메소드를 추가하거나 viewModel에 addPoint를 사용하여 stat를 첫 번째 매개 변수로 사용할 수 있습니다. '$ data'는 stats의 특정 항목이 될 것이고 당신은 그 데이터를 push 할 수 있습니다. –

1

는 "addPoint은 정의되지 않은"얻고있는 이유는 오류입니다. 템플릿 내에서 바인딩 컨텍스트는 뷰 모델이 아닌 통계 개체입니다.

결론 : 녹아웃이 존재하지 않는 stat.addPoint 기능을 찾고있어 오류가 발생합니다.

아마도 부모 바인딩 컨텍스트 인 뷰 모델을 참조하면됩니다. KO 1.3 베타에서, 당신이 할 수있는 access parent binding contexts 같은 : 당신이 컨텍스트 바인딩 부모에 대한 액세스를 제공하지 않습니다 마네의 이전 버전에 붙어있는 경우

<button data-bind="click: $.parent.addPoint">Add Point</button> 

이 알려, 몇 가지 추가 옵션이 있습니다 뷰 모델을 전역으로 액세스 할 수있게 만든 다음 해당 정규화 된 이름에 바인딩하는 등의 작업을 수행 할 수 있습니다.