Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Passing parameters to a function in knockoutjs viewmodel

Tags:

knockout.js

I have anchor tag like this

<a href="#" class="btn btn-success order-btn" data-bind="attr:{'data-tiername':$data.tierName, 'data-identifier' : $parent.identifier}, click: $root.setPath.bind($data,$data.tierName, $parent.identifier)">Send values</a>

In the viewmodel

var appViewModel = {
    setPath: function (data, tier, identifier) {
        alert(data);
        alert(tier);
        alert(identifier);
    },
...........
...........
}

The result is some knockoutjs core code being displayed in alert message (possibly definitions of observable(),dependentObservable() functions and [Object object] which is empty when alerted with JSON.stringify)

why does this work?

data-bind="attr:{'data-tiername':$data.tierName, 'data-identifier' : $parent.identifier}

but not this:

click: $root.setPath.bind($data,$data.tierName, $parent.identifier)

note that tierName is an observable(), identifier is computed()

Where can I find more about bind() ??

like image 724
nthapa Avatar asked Feb 23 '12 17:02

nthapa


2 Answers

Since tierName and identifier are observables, you need to call them to access to their values:

click: $root.setPath.bind($data, $data.tierName(), $parent.identifier())

Also, first argument in bind() will be bound to this in setPath, so I guess you need something like this:

click: $root.setPath.bind(/*will be bound to this*/ $root, $data, 
                      $data.tierName(), $parent.identifier())

Finally, if $data itself is an observable (which is not clear if it is from you code), then you need to call it as well:

click: $root.setPath.bind($root, $data(), $data().tierName(), $parent.identifier())

Also remember bind has been introduced in ECMAScript 5, so it may not be present in all browsers. So I would probably do something like this instead:

click: function(){$root.setPath($data, $data.tierName(), $parent.identifier());}

Here is additional info on bind.

like image 116
Roman Bataev Avatar answered Sep 17 '22 20:09

Roman Bataev


The first parameter to bind is the target (what you want this to be) when your function is executed. So, if you want data to be the first argument, then it needs to be the second argument.

Inside your function, if you are dealing with observables or computed observables, then you need to unwrap them to see their value. You would do this either by calling it as a function alert(data()); or by calling alert(ko.utils.unwrapObservable(data)); (which is generally used when you don't know at design type if what you are going to be dealing with is an observable or a non-observable.

The reason that attr and other bindings work when you pass an observable/computed observable is that they all call ko.utils.unwrapObservable for you for convenience (so you don't have to add () when passing observables unless you are writing an expression !$data().

Here is some reference on bind: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Function/bind

like image 23
RP Niemeyer Avatar answered Sep 18 '22 20:09

RP Niemeyer