Trying to get basic Knockout click binding set up, as per the example below:
<button id="btn-a" class="btn" data-bind="css: {'btn-primary':mode() == 'manual'}, click: $root.mode('manual')">Manual</button>
<button id="btn-b" class="btn" data-bind="css: {'btn-primary':mode() == 'automatic'}, click: $root.mode('automatic')">Automatic</button>
<label>MODE: </label><span data-bind="text:mode()"></span>
<script>
$(function () {
var TestModel = function() {
var self = this;
this.mode = ko.observable('manual');
};
var testModel = new TestModel();
window.testModel = testModel;
ko.applyBindings(testModel);
});
Fiddle: http://jsfiddle.net/aq85wk65/
However, running into two issues:
- The binding causes the
mode()
value to start out as 'automatic', even though we explicitly initialize it to 'manual'. - Whenever a button is clicked, the javascript console shows:
Uncaught TypeError: h.apply is not a function
The problem is that your
click
handler is invoking the function instead of using its reference.That's why you're ending up with
mode
beingauto
, becauseclick: $root.mode('automatic')
is setting the observable value.Try this instead:
Either the
.bind
answer or thefunction() {}
answer will work; but generally I prefer to avoid defining functions in my views where possible, and instead move that logic to the ViewModel.So another option, and the one I'd probably go with in this case is to define a
viewModel.setToManual()
function and aviewModel.setToAutomatic()
function.Then the binding handler would just be
Not only is that cleaner in the view, but it protects the view against changes to the ViewModel's structure as well, as long as the behavior of
setToAutomatic
(and probably a comparableisAutomatic
) are preserved.You need to wrap your click handlers in function:
http://jsfiddle.net/aq85wk65/1/
see http://knockoutjs.com/documentation/click-binding.html