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?
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 .
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.
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.
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>
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());
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/)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With