Search code examples
ember.jsember-cli

How to implement a search feature?


I have a search feature that allows the user to filter out by products. Typically, I would have the following:

// Routes
import Ember from 'ember';

export default Ember.Route.extend({
  model: function(params) {
    return Ember.RSVP.hash({
      keyword: params.keyword,
      products: this.store.find('product', { name: params.keyword, status: 'available' })
    });
  },

  setupController: function(controller, model) {
    controller.set('content', model);
  }
});

In the template:

// Template
{{#if products.length}}
  <ul>
    {{#each products}}
      <li>
        Name: {{name}}
      </li>
    {{/each}}
  </ul>
{{else}}
  <p>No products</p>
{{/if}}

Which works. However, what if I wanted a search API endpoint to handle filtering of products...

How will the model hook in the routes look like? Should I create an Ember search model? Is that the right approach?

If not, should I be using Ember.$.ajax instead? Other approach?


Solution

  • Ember.js provides facilities to deal with _query_ing data at resource level. Here is a suggested solution followed by some other options that are closer to your expectations.

    Expected Use Case

    1. In Ember, you don't have to map your "representation" of data to your server endpoint. You don't have to be RESTful with your Ember routes (as in URLs).
    2. In Ember, one "representation" of data (say a Controller and View set) can consult multiple data sources.
    3. Use "q" parameter for full text search on your resource.
    4. The point behind all of this is, to decrease complexity of your backend API. If you build a search and query system for one resource, you can reuse it for all other resources of your backend.

    Create a search URL

    // in your router
    this.route('search')
    

    Create a search Route to fetch required data

    Ember.RSVP.hash({
      stores: this.store.find('store', {
        rate_minimum: 4.0,
        near: 'lat:long',
        q: 'local store name'
      }),
    
      products: this.store.find('product', {
        price_maximum: '$50',
        near: 'lat:long',
        q: 'famous shoe brand'
      })
    });
    

    Fast Response Way

    Use Store#pushPayload

    Download data with Ember.$.ajax from your search endpoint. Keep in mind as long as your data has a name, you can use Store#pushPayload to load multiple unrelated data types into Ember Data's Store.

    In your Route's model hook, use this.store.all('product') to return all products in memory without sending a request. At some point in future Ember will update this array. You can use Ember.RSVP to "represent" more than one resource.

    In your Controller, use array operations like filterBy to provide real time update to users' queries beside issuing a new request to API for more relevant data.

    This results in immediate response while waiting for backend to reply and immediately updating "representation" of data with backend response.

    Ember Data-less Way

    1. Create a Search Route
    2. Use Ember.$.ajax to get data
    3. Pass it as your Route's model hook
    4. Send another ajax request whenever user changes search criteria