I just implemented this in my own app and it can be a bit tricky. First, you'll want to add an input field into your app for users to use to search and bind it to a property on your controller:
{{input value=search classNames='form-control' placeholder="Search books"}}
As you see above, it's bound to the search property of your controller and I've given it the default Bootstrap class form-control
Now, let's make a new computed property in your controller called books:
App.BooksIndexController = Ember.ArrayController.extend({
...
books: function() {
var model = this.get('model');
var search = this.get('search');
var current = 1;
var books = model.filter(function(item) {
var reg = '.*'+search.toLowerCase()+'.*';
var name = item.get('name').toLowerCase();
if(name.match(reg) && current < 20) {
current++;
return true;
}
});
return books;
}.property('search','model.length')
...
});
What this does it get all your items for you model and checks to see if the name property matches the name of any of the books in the model. You can change which property it matches or add new ones as you like. I don't like all the matched items being returned at once, so I add a limit with current so that only the first 20 matches are returned. You can remove this if you like. Doing it this way means you'll automatically display items that match that's already in the store.
Now, update your template so it iterates over books instead of model or some such stuff:
{{#each book in books}}
// do stuff with each book
{{/each}}
This is great you say! Now you're filtering all your books as you type because the books property will be updated whenever search is modified, but now you need to fetch new items from your API. We do this with another computer property:
searchApi:function() {
var search = this.get('search');
var books = this.store.find('books',{search_text: search});
var model = this.get('model');
books.then(function() { // In my tests, this isn't
model.addObjects(books); // actually necessary, bit I still
}); // like to keep it for clearness
}.observes('search').on('init')
This will trigger a search of your API whenever the search field is modified as well. Any matched items are then added to the model. That's why we added model.length to the books computed property. Any matched items will be added to the model and increase its length, triggering books to be updated again.
That should be everything you need. No new routes or controllers, just do it right in the index. If anyone has a cleaner approach to this, I'd love to see it!