2012-07-02 7 views
32

ノックアウトの「チェック済み」バインディングに問題があります。チェックボックスの "change"イベントは、更新前に古い値を返しているようです(チェックされていない場合は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ています。しかし、チェクボックスが変更されると、常に古い値を送出し、メソッドをトリガして値を変更します。これを修正する方法はありますか?

+1

コードに問題があります。 'ShowOpened'と' IsUpdated'のどちらもko.observablesではありません(あなたがいつも古い値を取得している理由でしょう)。このコードはどのように機能しますか? 'CategoryChange'は例外を投げます。 – freakish

+1

@freakishあなたがライトだから、この投稿を作成するときに間違いを犯しました。しかし、あなたが指摘したエラーはまだ問題ではありません。 – akhabaiev

+0

Oi、まだこれが欠けています: 'this.ShowOpened = ko.observable(ShowOpened);'これと 'pCategory.ShowOpened()'。私は、このポストを書いている間、あなたは多くの間違いをしたと言わなければならない... – freakish

答えて

57

ようになります方法です、私は近いそれを見てきました。あなたが正しいと思われます! changeイベントはの前に実行され、の前に実際の値が設定されます。私はこれの理由を知らないのが怖いです。

しかし、この問題を解決する簡単な方法があります:ちょうどclickイベントにchangeイベントを変更:

<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. :) */ 
}); 
+1

偉大な、イベントの作品をクリックします。私はそれを試してみました、真実を返すことを忘れてしまいました。チェックボックスはチェック/チェックされませんでした。ありがとう。 – akhabaiev

+0

私は、IEで 'change'イベントを認識しないという全く同じ問題がありました。 Grr。 – Brandon

+5

完璧に動作します!ありがとう。 「真実を返す」これが正しく動作するための鍵です! – mikemike396

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); 

または(より良い解決策と私の意見では)代替として、あなたが今computedと呼ばれる、dependentObservableを使用することができます動作するはずです。ここでは、ko.observablesの欠如が問題ではないことを示すに持続しているので、それは

<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); 
0

私もこの問題を持っていましたが、私はすでに値をリセットすることができ、AJAX要求と同じフィールドに加入したので、私は購読するソリューションを使用することができませんでした。コードを変更すると、コードはループしたままになります。だから私は次の回避策を追加しました(その醜いですが、それは動作します)。

代わりに、変更を聞いて、私はafterChangeイベントを聞きます。

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

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

関連する問題