Search Bar Madness: a How-To for Ember.js

Beth Jaswa
gSchool Stories
Published in
4 min readFeb 5, 2015

In an effort to understand how to add a search bar to my Ember app (a class project), I’ve compiled something that I wish I had when I was struggling to set it up. It might not be in the most logical order since I am writing this after I’ve figured it out.

For this example, it assumes that in the router you have a search route nested under the posts route.

Add the Physical Search Bar to the Template

{{input type=”text” class=”search” placeholder=”Search” value=search action=”queryPost”}}

In my case, I added it to my posts.hbs because I wanted the search on my side bar. Therefore the action needs to be added to the posts controller.

Add a queryPost Action

This action is run when you hit enter to search. I created a variable called query which is set to the search bar’s value. Then I want to transition to a search template and pass queryParams with a value of the hash {term: query}. The user should be able to enter in a word to the search bar. Hit enter on their keyboard which will trigger the queryPost action which will fetch search bar’s value and set it to query. Then the user will transition (like a redirect in Rails) to the search template and pass in the value of term to whatever query is.

queryPost: function() { var query = this.get(‘search’); this.transitionToRoute(‘posts.search’, {queryParams: {term: query}}); }

Create a Template for the Search Results

I decided to have a sentence that would restate what was inputed into the search bar. Then I iterated over each post in the model to display the title and body of posts. Originally this just displayed all posts which is fine for now.

Create a Controller

Next I gave the search controller queryParams with a value of [‘term’]. Then gave the controller term with a value of null.

Create a Route

Next I added a search route and a model within that. The model function accepts params and says if the params have a key of term, then it will return what the store finds that matches the term. Otherwise it will return an empty array so nothing will get searched.

return this.store.find(‘post’, {find: params.term});

Test the Rails API without Ember

Use Postman to see the json that’s rendered from your index action. Enter a request url as a GET request.

http://localhost:3000/posts?find=A

This should return an empty array of posts.

Your Rails Posts_Controller

Next I added some logic and queried the database. So in sudo code: If params with a key of find, then filter all posts where title equals the value of find. Otherwise render the normal json for all the notes. At first I just hardcoded title: “A” because I had a title of “A”, then I changed it to equal the value. This doesn’t work like a normal search bar yet. Right now it should only return the post if you search an exact title.

Once that works — check with Postman and in your Ember app — then update the database query to work how you’d expect it to. Disclaimer: I’m using SQLite as my database. Now update the query to SQL and something like this:

Post.where("title like ? OR body like ?", "%#{ some_variable }%", "%#{ some_variable }%")

some_variable will be the value of the find key (let’s call the value input for this example) will read like this:

Find the posts WHERE title is LIKE input OR body is LIKE input. The % surrounding some_variable allows it to search within body or title for that given word.

Make sure to render json: results_of_your_query

Test it out. Embrace Mr. Postman. Double check the Rails server in the console to make sure it’s happy. If that’s all good, then try it in your Ember app.

But wait? I have this bug where I search for x and then want to search for y and it doesn’t ever search for y but the path changes!

Well at least you know the problem isn’t in your Rails API because Postman returned different posts for different search results.

Let’s jump back into the search controller. Term is initially null. After we search for something, term is changed to whatever word we searched. Now we need to be able to change term’s value again to the next word that we search.

Handlebars.js doesn’t allow you have functions in a template, so instead we’ll write the function in the search controller and refer to it in the view/template. I wrote a function called results that returns what the Store finds within the post model and sets the value to the find key to this’s term value. Then it will change the value property of term. It looks like this:

results: function () { return this.store.find(‘post’, {find: this.get(‘term’)}); }.property(‘term’)

Then go back to your template and update your each loop to look for post in results instead of post in model. Now it will only display the latest search results as you would expect!

Turns out now I don’t need what I wrote in the search route model. I actually don’t need any of it. Between the results function and setting term to null, term will return an empty array if given no search term and then will reset term for each search result.

--

--

Beth Jaswa
gSchool Stories

Engineering Leader. Enjoys Tasty Food and Beverages. Wishes Upon a Star (Disney Fanatic).