使两个领域与淘汰赛互相排斥

时间:2014-08-21 17:31:06

标签: javascript knockout.js

我正在尝试将文本输入和复选框互斥。

默认情况下,文本框应包含" 0"并且复选框应为false。如果用户选中该复选框,则应清空文本框。如果用户在文本框中输入值,则应取消选中该复选框。任何一个领域都不应该被禁用或者不可编辑。

尽管有一个小的淘汰赛相关的讽刺,我几乎所有的行为都有效。如果用户在文本框中键入数字,然后单击该复选框,同时仍然关注文本框,则文本框值将不会清除。

我认为这种情况正在发生,因为订阅会被解雇,但我不确定如何解决。

标记:

<div id="container">
    <label>Number: </label><input type="text" data-bind="value: number" /> OR
    <input type="checkbox" id="all" data-bind="checked: all" /><label  or="all">All</label>
</div>

脚本:

var ViewModel = function () {
    var self = this;

    self.number = ko.observable(5);
    self.all = ko.observable(false);

    var updatedFromUser = true;

    self.number.subscribe(function (updatedNumber) {
        if (!updatedFromUser) {
            updatedFromUser = true;
            return;
        }

        updatedFromUser = false;
        self.all(updatedNumber === '');
    });

    self.all.subscribe(function (checked) {
        if (!updatedFromUser) {
            updatedFromUser = true;
            return;
        }

        updatedFromUser = false;
        if (checked) {
            self.number('');
        } else {
            self.number(0);
        }
    });
};

http://jsfiddle.net/rpnmvw1u/1/

1 个答案:

答案 0 :(得分:2)

默认情况下,value binding更新change事件中的基础observable,这通常发生在您离开文本框时,这就是为什么您的代码在单击复选框时仍无法正常工作,同时仍然专注于文本框。

您可以使用valueUpdate选项更改此行为:将其设置为afterkeydown会在用户输入文本框的内容时更新您的observable:

<input type="text" data-bind="value: number, valueUpdate: 'afterkeydown'" />

但是,它本身不会修复您的代码,因为您当前的updatedFromUser用法并不总是正常运行。

我会使用为all属性计算的可写:

self.number = ko.observable(5);
self.all = ko.computed({
    read: function () {
        return self.number() === '';
    },
    write: function (checked) {
        if (checked) {
            self.number('');
        } else {
            self.number(0);
        }
    }
});

演示JSFiddle

在这种情况下,KO将为您处理订阅,并且没有依赖关系圈,因为只有all取决于number