I am trying to understand knockout. And there is a thing I don't understand. We have html:
<p>
<input type='checkbox' data-bind="checked: hasCellphone" />
I have a cellphone</p>
<p>
Your cellphone number:
<input type='text' name='cell' data-bind="value: cellphoneNumber, enable: hasCellphone" /></p>
<button data-bind="enable: document.getElementsByName("cell")[0].value != '555'">
Do something</button>
And JS:
function AppViewModel() {
this.hasCellphone = ko.observable(false);
this.cellphoneNumber = ko.observable("");}
ko.applyBindings(new AppViewModel());
So, enable for input works, but not for the button, even if I enter '555' into the input it still stays enabled.
I am trying to understand knockout. And there is a thing I don't understand. We have html:
<p>
<input type='checkbox' data-bind="checked: hasCellphone" />
I have a cellphone</p>
<p>
Your cellphone number:
<input type='text' name='cell' data-bind="value: cellphoneNumber, enable: hasCellphone" /></p>
<button data-bind="enable: document.getElementsByName("cell")[0].value != '555'">
Do something</button>
And JS:
function AppViewModel() {
this.hasCellphone = ko.observable(false);
this.cellphoneNumber = ko.observable("");}
ko.applyBindings(new AppViewModel());
So, enable for input works, but not for the button, even if I enter '555' into the input it still stays enabled.
Share Improve this question edited Jan 30, 2013 at 10:06 Jan Hančič 53.9k17 gold badges98 silver badges101 bronze badges asked Jan 30, 2013 at 9:53 SkeeveSkeeve 1,2553 gold badges16 silver badges31 bronze badges 3- 1 What's your parseAreaCode method? Is it definitely returning the correct value? – Paul Manzotti Commented Jan 30, 2013 at 9:55
- Sorry, wrong code here, I've just copied it from here knockoutjs./documentation/enable-binding.html, I'll edit is as I tried to use it. – Skeeve Commented Jan 30, 2013 at 9:58
- Oh! Post your code then, as what you've posted should work, as long as you implement parseAreaCode correctly. – Paul Manzotti Commented Jan 30, 2013 at 9:59
3 Answers
Reset to default 5The example on the knockout page is a bit misleading. The enable binding takes any value but for automatic updates it must be an observable. document.getElementsByName("cell")[0].value != '555'
is not an observable.
You can fix the code easily by adding a cellphoneNumberValid
observable to the model which is based on the value of the cellphoneNumber
observable:
html
<p>
<input type='checkbox' data-bind="checked: hasCellphone" />
I have a cellphone
</p>
<p>
Your cellphone number:
<input type='text' name='cell' data-bind="
value: cellphoneNumber,
valueUpdate: 'afterkeydown',
enable: hasCellphone" />
</p>
Do something
js
function parseAreaCode(s) {
// just a dummy implementation
return s.substr(0, 3);
}
function AppViewModel() {
this.hasCellphone = ko.observable(false);
this.cellphoneNumber = ko.observable("");
this.cellphoneNumberValid = ko.puted(function() {
return parseAreaCode(this.cellphoneNumber()) != '555';
}, this);
}
ko.applyBindings(new AppViewModel());
jsfiddle
http://jsfiddle/bikeshedder/eL26h/
You need the enable condition to be an observable, otherwise knockout doesn't check to see if the value has changed. You've just got it bound to an html element, which won't notify knockout when its value has changed. What happens if you try:
<button data-bind="enable: cellphoneNumber() != '555'">Do something</button>
Here is the easiest way to make this right, especially if you don't want to change your model. Big thanks to bikeshedder for his answer.
http://jsfiddle/NickBunich/C5vfV/2/
<p><input type='checkbox' data-bind="checked: hasCellphone" />
I have a cellphone</p>
<p>Your cellphone number:
<input type='text' data-bind="value: cellphoneNumber, valueUpdate: 'afterkeydown', enable: hasCellphone" /></p>
<button data-bind="enable: cellphoneNumber().trim().substr(0,3) !='555'">Do something</button>
function AppViewModel() {
this.hasCellphone = ko.observable(false);
this.cellphoneNumber = ko.observable("");}
ko.applyBindings(new AppViewModel());