ノックアウト「チェック済み」バインディングに問題があります。チェックボックスの「変更」イベントは更新される前に古い値を返すようです(チェックされていない場合は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チェックボックスがあります(後で更新されるオブジェクトを知る必要があります)。ただし、チェックボックスが変更されると、常に古い値、トリガー方法、および値が送信されます。これを修正する方法はありますか?
ko.observables
の欠如は問題ではないと断言し続けたので、私はそれを詳しく調べました。あなたは正しいようです! change
イベントが発生しますbefore実際の値が設定されます。私はこの理由がわからないのではないかと心配しています。
しかし、これを修正する簡単な方法があります:change
イベントをclick
イベントに変更するだけです:
<input type="checkbox" data-bind="checked: ShowOpened, click: $root.CategoryChange" />
click
イベントハンドラの最後にreturn true;
を明示的に配置する必要があることに注意してください。そうしないと、新しい値はチェックボックスに設定されません。
click
イベントを使用したくない場合は、他の方法で実行できます。 ShowOpened
の変更をサブスクライブします。
this.ShowOpened = ko.observable(ShowOpened);
this.ShowOpened.subscribe(function(newValue) {
/* Do something when ShowOpened changes.
newValue variable holds the new value, obviously. :) */
});
イベントバインディングの代わりに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);
私もこの問題を抱えていましたが、値をリセットできる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>
私はそれが最善の解決策ではないことを知っていますが、私の場合は他の選択肢がありませんでした。