2011-09-30 31 views
0

これは期待どおりに動作するように近いです。 JSONリクエストからデータを取得してから、マッピングプラグインを使用してマップします。クリックバインディングでネストされた配列に新しい値を追加したい。knockout.mappingプラグインとknockoutjsで作成されたネストされたobservable配列に新しい値を追加

私のコードでは、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はグローバルスコープを持っていない場合は、あなたがtemplateOptions経由でそれを渡すことができ

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

:最も簡単な方法は次のようにあなたのViewModel変数にメソッドをバインドすることです。これは次のように次のようになります。

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

、好きそれを呼び出す:<button data-bind="click: $item.add">Add Point</button>

をおKO 1.3 betaを使用している場合は最後に、あなたが行うことができます:<button data-bind="click: $root.addPoint">Add Point</button>

+0

私は両方の方法を試してみました、私は取得していますエラー 'Uncaught TypeError:未定義のメソッド 'push'を呼び出すことができません'私は統計情報テンプレートにボタンを置いた理由は、新しい項目を各配列に独立して追加できるようにするためです。 –

+1

OK-あなたは本当にあなたのaddPointメソッドが 'stats'の特定の項目を扱うことを望んでいます。 'stats'のためのマッピングを追加してそこにaddPointメソッドを追加するか、viewModel上のaddPointに最初のパラメータとしてstatを渡すことができます。 '$ data'は統計情報の中の特定の項目になり、そのデータにプッシュすることができます。 –

1

ビューモデルの子プロパティのテンプレートの中にいるので、あなたが「addPointが定義されていません」というエラーを取得している理由があります。テンプレートの内部では、バインディングコンテキストはビューオブジェクトではなく、統計オブジェクトです。

ボトムライン:ノックアウトは存在しないstat.addPoint関数を探していますので、エラーが発生します。

あなたがしたいことは、親バインディングコンテキストであるビューモデルを参照することです。 KO 1.3ベータ版では、このようaccess parent binding contextsことができます:あなたは私に知らせて、親バインディングコンテキストへのアクセスを提供しないノックアウトの古いバージョンで立ち往生している場合は

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

、いくつかの追加オプションがありますビューモデルをグローバルにアクセス可能にしてから、その完全修飾名にバインドするだけです。

関連する問題