Live search with knockout.js
Knockout.js is an interesting take on building rich web applications. While I was initially turned off by the MVVM approach of embedding bindings in the view, it has grown on me after playing around with it for a few days. I look forward to experimenting with it on a larger application.
My first experimentation with knockout is to implement live search. Here is a demo of searching for beers by name:
How to build it
To start with, we just want to display our list of beers. Once we get that done, then we can start implementing the search. I used a hard-coded list for this example, but this could easily be the result of an API request.
var beers = [ {name:"…", brewery:"…", style:"…"}, // … ];
We need to tell knockout about these beers so we can bind them to the view.
var viewModel = { beers: ko.observableArray(beers) }; ko.applyBindings(viewModel);
Displaying this list of beers is simple. We create our markup for the list, and use knockout’s template binding.
<ul data-bind="template: {name:'beer', foreach:beers}"></ul> <script type="text/html" id="beer"> <li> <strong data-bind="text: name"></strong> – <span data-bind="text: brewery"></span> – <span data-bind="text: style"></span> </li> </script>
Now we should be able see our list of beers. Next let’s implement the search functionality, starting with an input field to search with.
<input placeholder="Search…" type="search" data-bind="value: query, valueUpdate: 'keyup'" autocomplete="off">
The data-bind attribute tells Knockout that we want to bind the value of this input field to a variable called query, and we want to update that value on keyup. We need to set up query as an observable attribute.
var viewModel = { // … query: ko.observable('') }
Whenever the query attribute is changed, we want to perform our search and update our list of beers, so we subscribe to updates on query and call a search function.
var viewModel = { // … search: function(value) { // remove all the current beers, which removes them from the view viewModel.beers.removeAll(); for(var x in beers) { if(beers[x].name.toLowerCase().indexOf(value.toLowerCase()) >= 0) { viewModel.beers.push(beers[x]); } } } }; viewModel.query.subscribe(viewModel.search);
Our search function begins by removing all the beers from the array observed by knockout, then loops through our list of beers and does a simple search, adding each beer back to the knockout array if it matches, which in turn updates it in the view.
View the source on the demo to see all of the code in context.
4 Comments
Hello- Glad that you are enjoying Knockout. I wanted to offer an alternate implementation for you to look at: http://jsfiddle.net/rniemeyer/cCBqJ/
Not drastically different, it just shows how you can use a dependentObservable that will get re-evaluated whenever your query changes.
I look forward to future posts on Knockout.js!
Ryan: awesome, thanks for chiming in! I wasn’t sure if I was doing it the knockout way, but was happy with how concise the code was anyway.
I’ll update the post to use this method.
Very interesting. But what is the list of beer’s were to come from some database (more realistic)
Bhaarat: Knockout doesn’t really care how you get the list. So you could easily update search function above with an Ajax call using jQuery or your library of choice, and when the results come back, append them to the array observed by knockout.
Post a Comment