35

ノックアウトの「チェック済み」バインディングに問題があります。チェックボックスの「変更」イベントは、更新される前に古い値を返すようです(したがって、チェックされていない場合はfalseが返されます)。オブジェクト内にあるので、値をサブスクライブできないと思います。

<tbody data-bind="foreach: Categories">
                <tr>
                    <td><input type="checkbox" data-bind="checked: ShowOpened, event: { change: $root.CategoryChange }" /></td>
                </tr>
            </tbody>
<script type="text/javascript">
var Category = function (Id, Name, Order, ShowOpened) {
    this.Id = Id;
    this.Name = Name;
    this.Order = Order;
    this.ShowOpened = ShowOpened;
    this.IsUpdated = ko.observable(false);

    this.OldOrder = Order;
    this.OldShowOpened = ShowOpened;
};
var ViewModel = {
    Categories: ko.observableArray([]),
    CategoryChange: function(pCategory) {
        if(pCategory.Order != pCategory.OldOrder || pCategory.ShowOpened != pCategory.OldShowOpened)
            pCategory.IsUpdated(true);
        else
            pCategory.IsUpdated(false);
    }
};
ko.applyBindings(ViewModel);
</script>

したがって、この例では、オブジェクト内の変数を変更するCategoryChangeメソッドをトリガーできるShowOpenedチェックボックスがあります(後でどのオブジェクトが更新されるかを知る必要があります)。ただし、チェックボックスが変更されると、常に古い値、トリガーメソッドが送信され、値が変更されます。これを修正する方法はありますか?

4

3 に答える 3

66

あなたは不足はko.observables問題ではないと言い続けたので、私はそれを詳しく調べました。あなたは正しいようです!changeイベントは、実際の値が設定される前に発生します。理由がわからないのではないかと思います。

ただし、これを修正する簡単な方法があります。changeイベントをclickイベントに変更するだけです。

<input type="checkbox" data-bind="checked: ShowOpened, click: $root.CategoryChange" />

イベントハンドラreturn true;の最後に明示的に配置する必要があることを忘れないでください。clickそうしないと、新しい値がチェックボックスに設定されません。

clickイベントを使用したくない場合は、別の方法で使用できます。の変更を購読するShowOpened

this.ShowOpened = ko.observable(ShowOpened);
this.ShowOpened.subscribe(function(newValue) {
    /* Do something when ShowOpened changes.
       newValue variable holds the new value, obviously. :) */
});
于 2012-07-02T15:10:38.430 に答える
6

subscribeイベントバインディングの代わりに使用してみてください。これは今動作するはずです

<table>
    <tbody data-bind="foreach: Categories">
        <tr>
            <td><input type="checkbox" data-bind="checked: ShowOpened" /></td>
        </tr>
    </tbody>
<table>

var Category = function (Id, Name, Order, ShowOpened) {
    this.Id = Id;
    this.Name = Name;
    this.Order = Order;
    this.ShowOpened = ko.observable(ShowOpened);
    this.IsUpdated = false;

    this.OldOrder = Order;
    this.OldShowOpened = ShowOpened;

    this.ShowOpened.subscribe(function (newShowOpened) {
        if(this.Order != this.OldOrder || this.ShowOpened() != this.OldShowOpened)
            this.IsUpdated = true;
        else
            this.IsUpdated = false;
    }, this);
};
var ViewModel = {
    Categories: ko.observableArray([])
};
ko.applyBindings(ViewModel);

または、代わりに(そして私の意見ではより良い解決策として)dependentObservable、現在はと呼ばれているを使用できますcomputed。これがどのように見えるかです

<table>
    <tbody data-bind="foreach: Categories">
        <tr>
            <td>
                <input type="checkbox" data-bind="checked: ShowOpened" />
                <span data-bind="text: IsUpdated"></span>
            </td>
        </tr>
    </tbody>
</table>
var Category = function (Id, Name, Order, ShowOpened) {
    this.Id = Id;
    this.Name = Name;
    this.Order = Order;
    this.ShowOpened = ko.observable(ShowOpened);
    this.OldOrder = Order;
    this.OldShowOpened = ShowOpened;
    this.IsUpdated = ko.computed(function () {
        return this.Order != this.OldOrder || this.ShowOpened() != this.OldShowOpened;
    }, this);
};
var ViewModel = {
    Categories: ko.observableArray([])
};
ko.applyBindings(ViewModel);
于 2012-07-02T14:37:55.153 に答える
0

私もこの問題を抱えていましたが、値をリセットする可能性のあるajaxリクエストで同じフィールドに既にサブスクライブされていたため、サブスクライブソリューションを使用できませんでした。コードを変更すると、コードはループにとどまります。そこで、次の回避策を追加しました(醜いですが機能します)。

$("input[type='radio'], input[type='checkbox']", element).on("change", function (e, data) {
    setTimeout(function () {
        $(this).trigger("afterChange", data);
    }.bind(this), 10);
}); 

次に、変更をリッスンする代わりに、afterChangeイベントをリッスンします。

<div data-bind="foreach: answerList">
    <input type="checkbox" data-bind="event: { afterChange: $root.sendSelectedAnswer($data) }"/>
</div>

私はそれが最善の解決策ではないことを知っていますが、私の場合、他の選択肢はありませんでした。

于 2017-01-11T11:05:30.087 に答える