2012-07-02 49 views
32

我遇到了敲除「已檢查」綁定的問題。看起來,複選框中的「更改」事件在更新之前返回舊值(因此,如果它未被選中,它將返回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> 

因此,在這個例子中,我ShowOpened複選框,可以觸發CategoryChange方法,將改變內部對象的變量(即我需要後來知道是什麼更新的對象)。但是,當chechbox被改變時,它總是發送舊值,觸發方法,然後更改值。有沒有什麼辦法解決這一問題?

+1

你的代碼有問題。 ShowOpened和IsUpdated都不是ko.observables(也許這就是爲什麼你總是得到舊值)。這個代碼如何工作? 'CategoryChange'應該拋出異常。 – freakish

+1

@freakish你好,我最初創建這個帖子時犯了一個錯誤。但你指出的錯誤仍然不是問題。 – akhabaiev

+0

Oi,仍然缺少這個:'this.ShowOpened = ko.observable(ShowOpened);'和this:'pCategory.ShowOpened()'。我必須說,在寫這篇文章的時候你犯了很多錯誤... – freakish

回答

57

既然你堅持上指出,缺乏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. :) */ 
}); 
+1

很棒的點擊事件。我試過了,只是忘了返回true,並且複選框從未被選中/取消選中。謝謝。 – akhabaiev

+0

我對IE沒有識別'change'事件有完全相同的問題。格兒。 – 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); 

或者作爲替代(在我看來更好的解決方案),可以使用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); 
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> 

我知道它不是最好的解決方案,但在我的情況下,我沒有其他選擇。