I have a question with an array of answers. Each answer has a boolean property called isRight, which represents whether the answer is...right.
I'm trying to render a radio button for each answer, and have it be checked if that answer is right. If the user clicks a different button, that answer becomes correct.
I understand that KO binds the checked property to a value, and each radio button will only be checked if the radio's value matches the bound value; you can't just bind directly to isRight.
I put a computedObservable on the question itself, which should do all that. And it works. The problem is, I want to subscribe to the change event of the radio button, to see when a new answer is selected (and send an ajax request). The problem I'm having is that the ko binding is not updated in the change handler. It seems putting a delay in the handler will give me what I want, but I'd prefer a more direct solution.
And it seems the click event works perfectly, but that'll fire each time a radio button is clicked, even if it's already checked.
Is there any way to ensure that the binding is updated in the change event? Current code is ko 2.0, and I've also tried 2.1.
Full Source:
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>