Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout firing click binding on applyBindings

Recently I've separated out ViewModel to a separate JavaScript file.

var Report = (function($) {
    var initialData = [];
    var viewModel = {
        reports: ko.observableArray(initialData),
        preview: function(path) {
            // preview report
        },
        otherFunctions: function() {}
    };
    return viewModel;
})(jQuery);​

Here is the HTML and Knockout related code

<script type="text/javascript" src="path/to/report/javascript"></script>
<script type="text/javascript">
    $(document).ready(function () {
        ko.applyBindings(Report, document.body);
    });
</script>

HTML user interface has a button on which click is data bind to preview function in the view model

<input type="button" name="Preview" id="Preview" class="btnPreview" 
    data-bind="click: Report.preview('url/to/report')" />

Problem preview method is called when the following line execute in $(document).ready() function

ko.applyBindings(Report, document.body); 

That is without user clicking on the Preview button preview function is fired. What could be the reason for this behavior? The whole stuff was working fine when I'd view model JavaScript in the HTML page itself.

like image 885
Raj Avatar asked Apr 12 '12 08:04

Raj


People also ask

What is applyBindings in Knockout?

applyBindings do, The first parameter says what view model object you want to use with the declarative bindings it activates. Optionally, you can pass a second parameter to define which part of the document you want to search for data-bind attributes. For example, ko.

What is $parent in Knockout?

$parent : This is the view model object in the parent context, the one immeditely outside the current context. $root : This is the main view model object in the root context, i.e., the topmost parent context. It's usually the object that was passed to ko.

What is $data in Knockout?

The $data variable is a built-in variable used to refer to the current object being bound. In the example this is the one of the elements in the viewModel.


2 Answers

The reason is, that you're indeed invoking the preview function (because writing functionName means referring to the function, writing functionName() means calling it).

So data-bind="click: Report.preview" would be working as expected, but without handing over the parameter.

As the manual states (on a different topic, but this still applies):

If you need to pass more parameters, one way to do it is by wrapping your handler in a function literal that takes in a parameter, as in this example:

<button data-bind="click: function(data, event) { myFunction(data, event, 'param1', 'param2') }">
    Click me
</button>

or in your case:

data-bind="click: function() { Report.preview('url/to/report') }"

Another solution would be to make preview() return a function (pretty much the same thing actually):

preview: function(path) {
    return function() {
        // ...
    }
}
like image 92
Niko Avatar answered Oct 17 '22 07:10

Niko


Another solution is to use 'bind' construct:

data-bind="click: Report.preview.bind($data, 'url/to/report')" 

where the first parameter to bind() will become the 'this' in the called function.

like image 24
Remco Ros Avatar answered Oct 17 '22 07:10

Remco Ros