用计算的方法将KnockoutJS绑定到单选按钮

时间:2012-04-23 15:30:38

标签: javascript jquery knockout.js

我有一系列答案的问题。每个答案都有一个名为isRight的布尔属性,它表示答案是否正确。

我正在尝试为每个答案呈现一个单选按钮,并检查该答案是否正确。如果用户单击其他按钮,则该答案将变为正确。

我知道KO将checked属性绑定到一个值,只有当radio的值与绑定值匹配时才会检查每个单选按钮;你不能直接绑定到isRight。

我在一个问题本身上放了一个computedObservable,它应该完成所有这些。它有效。问题是,我想订阅单选按钮的更改事件,以查看何时选择了新答案(并发送ajax请求)。我遇到的问题是更改处理程序中没有更新ko绑定。似乎在处理程序中延迟会给我我想要的东西,但我更喜欢更直接的解决方案。

似乎点击事件完美无缺,但每次单击一个单选按钮时都会触发,即使它已经被检查过。

有没有办法确保在更改事件中更新绑定?目前的代码是ko 2.0,我也试过2.1。

Full Fiddle


完整来源:

function Question() {
    this.name = "My Question";

    var i = 0;
    this.answers = ko.observableArray([
        new Answer(++i, "Answer 1", false),
        new Answer(++i, "Answer 2", true),
        new Answer(++i, "Answer 3", false)]);

    this.correctAnswer = ko.computed({
        read: function () {
            for (var i = 0, max = this.answers().length; i < max; i++)
                if (this.answers()[i].isRight())
                    return "answer-" + this.answers()[i].id();
        },
        write: function (newValue) {
            var newId = +newValue.split('-')[1];
            for (var i = 0, max = this.answers().length; i < max; i++)
                this.answers()[i].isRight(this.answers()[i].id() === newId);
        },
        owner: this
    });
}


function Answer(id, name, isRight) {
    this.id = ko.observable(id);
    this.name = ko.observable(name);
    this.isRight = ko.observable(isRight);
}

$(function () {
    ko.applyBindings(new Question());

    $(document).on("change", "input[type='radio']", function () {
        var answer = ko.dataFor(this);
        var isRight = answer.isRight();

        setTimeout(function () { alert("before = " + isRight + "  after = " + answer.isRight()); }, 1000);
    });
});

HTML:

<div data-bind="text:name"></div>
<div data-bind="foreach:answers">
    <label>
        <span data-bind="text: name"></span>
        <input type="radio" name="uniqueQuestionName" data-bind="value: 'answer-' + id(), checked:$parent.correctAnswer" />
    </label>
    <br />
</div>

1 个答案:

答案 0 :(得分:4)

除非您有特定理由订阅“更改”事件,否则您可能需要考虑对正在更改的可观察对象使用manual subscription。这样,只要实际数据发生变化,您就会收到通知。

以下是使用略有不同的方法的示例:http://jsfiddle.net/rniemeyer/FvZXj/。它使用一个函数来处理设置值,该值将当前答案作为第一个参数传递。然后,它使用它来正确设置isRight和您可以订阅的可观察correctAnswer