Событие изменения флажка Knockout отправляет старое значение

У меня проблема с нокаутом "флажок" связывание. Кажется, что "изменить" событие в флажке возвращает старое значение, прежде чем оно будет обновлено (поэтому, если оно не было проверено, оно вернет 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 изменяется, он всегда отправляет старое значение, вызывая метод, а затем изменяет значение. Есть ли способ это исправить?

 akhabaiev02 июл. 2012 г., 16:31
@ freakish you 'reright, я ошибся при создании этого поста изначально. Но все же ошибка, на которую вы указали, не является проблемой.
 freakish02 июл. 2012 г., 16:40
Ой, все еще не хватает этого:this.ShowOpened = ko.observable(ShowOpened); и это:pCategory.ShowOpened(), Я должен сказать, что вы допустили много ошибок при написании этого поста ...
 freakish02 июл. 2012 г., 15:59
Что-то не так с вашим кодом. ниShowOpened ниIsUpdated являются ko.observables (и, вероятно, именно поэтому вы всегда получаете старое значение). Как этот код вообще может работать?CategoryChange должен бросить исключение.

Ответы на вопрос(3)

но я не мог использовать решение подписки, потому что я уже был подписан на то же поле с помощью запроса 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>

Я знаю, что это не лучшее решение, но в моем случае у меня не было другого выбора.

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);
Решение Вопроса

ko.observables это не проблема, я посмотрел на это поближе. Кажется, ты прав!change событие происходитbefore фактическое значение установлено. Боюсь, я не знаю причину этого.

Но есть простой способ исправить это: просто изменить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. :) */
});
 07 мая 2014 г., 14:25
Работает отлично! Благодарю. & Quot; вернуть true; & quot; это ключ к тому, чтобы это работало правильно!
 04 июл. 2015 г., 23:14
Приятно, что событие щелчка вызывается даже тогда, когда я нажимаю пробел и флажок имеет фокус.
 05 авг. 2013 г., 16:50
У меня была точно такая же проблема с IE, не признающимchange событие. Grr.
 akhabaiev02 июл. 2012 г., 18:20
Отлично, клик событие работает. Я попробовал это, прошу, просто забыл вернуть true, и флажок никогда не проверялся / не проверялся. Благодарю.
 24 сент. 2014 г., 08:23
Ух ты, это работает, похоже на ошибку в изменении: событие в нокауте для меня ...

Ваш ответ на вопрос