0

セットアップ:

「foreach:$data.items」のテンプレートを使用してテーブルを表示するknockout.jsアプリケーションがあります。

$ dataは、次のようにデータバインドで設定されます。

<div data-bind="template: {name: 'table-custom', data: {table: 'item-list-custom', config: $root.items, default: {foo: '', bar: ''}}}"></div>

$ root.itemsは、次のようなdictの配列です。

[{foo: 'val2', bar: 'val2'}, ...]

JSONから$root.itemsの値を取得し、テンプレートに従ってテーブルを作成します。

問題:

テーブルに新しい列を追加したかったので、そのデフォルト値を「デフォルト」のdictに追加しました(例:baz:'')。新しい列は選択としてレンダリングされます(ドロップダウンリスト)。

これまではすべてOKです。私の問題は:

1)選択したオプションが利用可能な場合、その値を設定するにはどうすればよいですか?私は試した

<select data-bind="value: baz, ...

しかし、(JSONからの)既存の行にはまだbazキーが含まれていないため、不満があり、それを見つけることができません。

2)選択範囲で値を選択すると、既存の行について、モデルの残りの部分と一緒に保存されません。つまり、まだ「foo」キーと「bar」キーのみが含まれています。

テーブルに新しい行を追加してから値を選択すると、正常に機能し、baz値が他の値と一緒に保存されます。これは、「デフォルト」のbaz値が新しい行に適用されるが、既存の行には適用されないためだと思います。

では、新しい行の場合と同じように、このセットアップを既存のデータ(後でテーブルに追加したため、ロード時に「baz」プロパティがない)で機能させるにはどうすればよいですか?

4

2 に答える 2

0

$dataプロパティの前に:を付けることで、これを実行できるはずです。

<select data-bind="value: $data.baz, ...

http://jsfiddle.net/amtiskaw/HD2jt/を示す小さなJsFiddleを作成しました。

于 2012-09-20T06:15:57.320 に答える
0

おそらくすべきことは、ビュー モデル ロジックをテンプレートから切り離し、それをクラスにカプセル化してから、テンプレートに渡すことです。これにより、(新しい列が追加されたり、サーバー側の JSON 構造が変更されたりしたときに) 必要な値にデフォルト値を設定するなど、さまざまな処理が可能になり、ビュー モデルがよりテストしやすくなります。また、行データのクライアント側での編集/追加/削除などを非常に簡単に実装できます。ポイント 2 については、ビュー モデルで ko.observable にすることで解決すると思います。

可能な実装のスニペットを次に示します。

function TableDefinition(tableName, tableConfig, options) {
    var self = this;
    tableConfig = tableConfig || {};

    // Create an instance of TableRow from each item in tableConfig
    var initialItems = ko.utils.arrayMap(tableConfig || [], 
                                       function(item) { return new TableRow(item); });
    self.config = ko.observableArray(initialItems);
    self.tableName = ko.observable(tableName);

    self.addRow = function() {
        // Allows you to instantly add a new row right from your page without relying on
        // the server-side structure
        self.config.push(new TableRow());
    };
    self.deleteRow = function(row) {
        self.config.remove(row);
    }
}

function TableRow(data) {
    var self = this;
    data = data || {};
    self.foo = ko.observable(data.foo || ''); // These are observables so that
    self.bar = ko.observable(data.bar || ''); // you can bind the values from
    self.baz = ko.observable(data.baz || ''); // control to view model
    self.selections = ['val1', 'val2', 'val3', 'val4']
}

これをルート ビュー モデルに追加し、サーバーからのデータをTableDefinitionビュー モデルに直接渡すことができます。

function RootViewModel(data) {
    var self = this;    
    self.table = new TableDefinition('item-list-custom', data);
}

そしてあなたのページで:

var dataFromServer = [
    {foo: 'val1', bar: 'val1'},
    {foo: 'val2', bar: 'val2'},
    {foo: 'val3', bar: 'val3'},
    {foo: 'val4', bar: 'val4'}]; // Dummy data, assumed to be retrieved from the server

var viewModel = new RootViewModel(dataFromServer);
ko.applyBindings(viewModel, document.getElementById('root'));

関連する JsFiddle は次のとおりです: http://jsfiddle.net/dflor003/BM3HU/

一番下にはライブ デバッグ ビューがあり、値を変更すると更新される JSON 形式でサーバーに送り返すデータの出力が表示されます。

于 2012-10-31T18:15:16.147 に答える