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>

所以在这个例子中,我有 ShowOpened 复选框,它可以触发 CategoryChange 方法,该方法将更改对象内部的变量(稍后我需要知道更新了哪些对象)。但是当 chechbox 被更改时,它总是会发送旧值、触发方法,然后更改值。有没有什么办法解决这一问题?

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 回答