Creating a Better Search Experience With Ember

Live updating searches are better for users. They provide real time results. They prevent misspellings, by allowing the user to adjust their keyword based on the results they’ve seen. When three letters match the thing you’re looking for you can stop typing, minimizing keypresses. With Ember, we can quickly and neatly create a live updating search experience. This post will describe how to create a live updating search that looks like the example below.
awesome example

One way to build this type of interactivity is to use a filter, which is sufficient for smaller data sets that are already in Ember Data’s store. However, when working with much larger datasets, which is often the case, querying needs to happen on the server.

The Non-Ember Way

Alright, so like me, perhaps you’ve built a similar feature before using jQuery and AJAX. Your instinct might be to bind keypress events to a function, collect the contents of the search input, and send an AJAX request back to the server, no problem. While this approach is feasible in Ember, it is counter to the framework conventions for a couple of reasons.

  1. One of Ember’s design pillars is storing application state in the url. By making an AJAX call directly, we lose integration with the router and the ability to update the URL as the search query changes.
  2. You would be circumventing Ember-Data. Anything you receive back from the server would not be automatically put in the store. This means we would lose serialization/deserialization of JSON, caching, and other smart things the store does for us.

To solve our problem in a more Emberish way, we will use Ember-Data and query params.

The Ember Way

Let’s assume we are searching through a large group of users by their name. First, let’s create our template, which would probably look something like this:

{{input value=search}}

<ul>
  {{#each user in model}}
    <li>{{user.name}}</li>
  {{/each}}
</ul>

We have a text input for our search query and a model which contains our search results. We iterate through the model and render each user name.
Next we’ll add a controller:

import Ember from "ember";

export default Ember.Controller.extend({
  queryParams: ['search'],
  search: ""
});

There are a few things to note about the controller.

  1. We have to define a search property so that our input can bind and update the search value.
  2. We have to tell Ember to treat our search property as a query param so that changes in our search property will manifest as URL changes.

Now, updating the input will update the query param, and additionally, if we visit /users?search=timothy, our input would automatically populate with a value of “timothy”.

Our final step is to wire our query param updates to our model. This is handled by a route:

import Ember from 'ember';

export default Ember.Route.extend({
  queryParams: {
    search: {
      refreshModel: true
    }
  },
  model: function(params) {
    return this.store.find('user', params);
  }
});

Our route also needs to be made aware of query param changes it should care about. We can use the refreshModel option to issue a request to the server every time the query params change. Whenever we update ‘search’ query param, the model will return a fresh batch of matching users. We just implemented a realtime updating search with only a few concise lines of code. Pretty neat Ember, pretty neat.

Tweet at Foraker

Share this post!