Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Knockout.js click binding with parameters

Tags:

knockout.js

I have this little ViewModel:

function BooksViewModel() {
    var self = this;
    self.books = ko.observableArray(library);

    self.findByLanguage = function(lang) {
        self.books = ko.computed(function() {
            return ko.utils.arrayFilter(library, function(book) { 
                return book.language() === lang; 
            });
        });
    };
}

The findByLanguage method filters the array by language. In the view, im tryign to implement that like this:

<ul class="dropdown-menu">
    <li><a tabindex="-1" href="#" data-bind="click: findByLanguage('C')">C</a></li>
    <li><a tabindex="-1" href="#" data-bind="click: findByLanguage('Cpp')">C++</a></li>
</ul>

I'm attemping to reuse the function by calling the language parameter from there. But if I pass a function with parenthesis on data-bind it automatically gets called.

How can I accomplish this?

like image 975
jviotti Avatar asked Nov 04 '12 17:11

jviotti


People also ask

How do you bind a function in Knockout JS?

The function you want to bind to the element's click event. You can reference any JavaScript function - it doesn't have to be a function on your view model. You can reference a function on any object by writing click: someObject. someFunction .

What is data bind click?

Click binding is one of the simplest binding and is used to invoke a JavaScript function associated with a DOM element based on a click. This binding works like an event handler. This is most commonly used with elements such as button, input, and a, but actually works with any visible DOM element.

What is data bind in Knockout JS?

Knockout's declarative binding system provides a concise and powerful way to link data to the UI. It's generally easy and obvious to bind to simple data properties or to use a single binding.


3 Answers

I know the question is old, but in case someone is interested, according to docs, first parameter should be a viewModel, then it works as expected.

<ul class="dropdown-menu">
    <li><a tabindex="-1" href="#" data-bind="click: findByLanguage.bind($data, 'C')">C</a></li>
    <li><a tabindex="-1" href="#" data-bind="click: findByLanguage.bind($data, 'Cpp')">C++</a></li>
</ul>
like image 162
Andrii Litvinov Avatar answered Dec 05 '22 23:12

Andrii Litvinov


You might be interested in a slightly different approach that add extra fields into your View Model.

http://jsfiddle.net/jearles/RN9Dw/

By adding languages into the View Model you can use Knockout to render the menu and the click binding will automatically pass the language that was clicked to the handler function. Additionally, adding selectedLanguage as an observable allows the books computed to change when you select or clear a language.

HTML

<ul class="dropdown-menu" data-bind="foreach: languages">
    <li><a tabindex="-1" href="#" data-bind="text: $data, click: $root.filterByLanguage"></a></li>
</ul>
<button data-bind="click: showAll">Show All</button>

<div data-bind="foreach: books">
    <p><span data-bind="text: name"></span>, <span data-bind="text: language"></span></p>
</div>​

JS

function BooksViewModel() {
    var self = this;

    self.languages = ko.observableArray(['C', 'C++']);
    self.selectedLanguage = ko.observable();
    self.library = [{name: 'Book A', language: 'C'}, {name: 'Book B', language: 'C++'}]; 
    self.books = ko.computed(function() {
        return ko.utils.arrayFilter(self.library, function(book) { 
          return self.selectedLanguage() == null ||
              book.language === self.selectedLanguage(); 
          })
    });

    self.showAll = function() {
        self.selectedLanguage(null);
    }
    self.filterByLanguage = function(lang) {
        self.selectedLanguage(lang);
    };
}

ko.applyBindings(new BooksViewModel());

like image 21
John Earles Avatar answered Dec 05 '22 23:12

John Earles


The easiest way to accomplish this would be to wrap this in a function that executes only on click, like:

<li><a tabindex="-1" href="#" data-bind="click: function () {findByLanguage('C')}">

Alternatively, you can use the bind context should do the trick.

<li><a tabindex="-1" href="#" data-bind="click: findByLanguage.bind('C')">

Here is an example of the click binding using JS Fiddle (http://jsfiddle.net/uFyaP/1/)

like image 38
Jamie Starke Avatar answered Dec 05 '22 23:12

Jamie Starke