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.
The 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:
<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
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());
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());