3

KnockoutJSを使用していますが、observableArray内のobservableオブジェクトが親に​​変更を通知する方法を知りたいです。次に例を示します。

http://jsfiddle.net/paragnair/CEEZ5/

HTML:

<h1 id="heading"> <text data-bind="text:childrenCount"></text> Fields selected</h1>
<table id="form">
<tbody data-bind="foreach:children">
    <tr>
        <td data-bind="text:name"></td>
        <td><input type="checkbox" data-bind="checked:isSelected"/></td>
    </tr>
</tbody>
</table>

<a href="#" id="btn-add">Add More Fields</a>​

Javascript:

var Child = function(name) {
    var self = this;
    self.name = ko.observable(name);
    self.isSelected = ko.observable(false);
},
    Parent = function() {
        var self = this;
        self.children = ko.observableArray([
            new Child('One'),
            new Child('Two'),
            new Child('Three')
            ]);
        self.children.subscribe(function(children) {
            header.childrenCount($.map(children, function(a) {                
                return a.isSelected() ? 1 : null;
            }).length);
        });
    },
    header = {
        childrenCount: ko.observable(0)
    };

var parentModel = new Parent(),
    extra = parentModel.children().length;
ko.applyBindings(parentModel, $('#form')[0]);
ko.applyBindings(header, $('#heading')[0]);

function setHeading(childrenCount) {
    header.childrenCount(childrenCount);
}

$(document).ready(function() {
    $('#btn-add').click(function() {
        extra++;
        parentModel.children.push(new Child('Extra ' + extra));
        return false;
    });
});​

上記の例では、選択したフィールド数で見出しを表示したいと思います。のsubscribeイベントがありobservableArrayますが、配列に何かが追加または削除された場合にのみ発生するため、ユーザーが実際にフィールドリストのチェックボックスをオンにしても、イベントは発生しません。これを実現する1つの方法は、チェックボックスにonchangeイベントを追加して、親のメソッドを呼び出し、次にオブジェクトのを更新する外部メソッドを呼び出すchildrenCountことheaderです。これを行うためのより良い方法はありますか?

4

2 に答える 2

6

これには別の方法でアプローチすると同時に、不必要な複雑さを取り除くことができると思います。モデルを個別のapplyBindings呼び出しに分割する必要はありません。実際、どうしても必要な場合を除いて、これを行うことはお勧めしません。これは、複雑さを増し、注意しないと二重バインディングが発生する可能性があるためです。

次に、ヘッダーがparentModelsの子の結果である場合、それは実際には同じモデルの一部である必要があります。KOモデルを作成するときに、OOPの原則を適用できます。これはそもそもKOを使用することを選択する利点です。

これが私があなたの問題を解決する方法です。

http://jsfiddle.net/madcapnmckay/edJyp/

var Child = function(name) {
    var self = this;
    self.name = ko.observable(name);
    self.isSelected = ko.observable(false);
},
Parent = function() {
    var self = this;
    self.children = ko.observableArray([
        new Child('One'),
        new Child('Two'),
        new Child('Three')
        ]);

    this.childrenCount = ko.computed(function() {
        var count = 0;
        ko.utils.arrayForEach(self.children(), function (child) {
            if (child.isSelected()) {
                count++;
            }
        });
        return count;
    });

    this.addMore = function () {
        self.children.push(new Child("Extra " + (self.children().length + 1)));
    };
};

var ViewModel = function () {
    var self = this;
    this.parentModel = new Parent();  
};

ko.applyBindings(new ViewModel());

ViewModelクラスは不要ですが、ここに表示されているよりも多くの機能があり、これにタグ付けされていると思います。

余談ですが、ボタンにjqueryクリックハンドラーを使用する必要があると感じたのはなぜですか?私はこの間違いを頻繁に目にし、ドキュメントの何があなたをその道に導いたのか疑問に思っていましたか?これは、例で行ったviewModelにも移動できます。

お役に立てれば。

于 2012-05-29T18:11:14.153 に答える
2

最後に、サブスクライブを使用しませんでしたが、次に外部関数を呼び出すを使用しeventました。更新されたフィドルは次のとおりです:http://jsfiddle.net/paragnair/CEEZ5/5/data-bindsetHeading

于 2012-06-25T17:16:22.277 に答える