Reputation: 18909
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?
Upvotes: 10
Views: 37849
Reputation: 13182
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>
Upvotes: 3
Reputation: 7194
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.
<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>
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());
Upvotes: 9
Reputation: 9234
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/)
Upvotes: 24