8daepg
Last Updated: February 25, 2016
·
4.819K
· ram9cc
8323e87e8f59ccc314fe9cfe74185e8c

Chaining Sorting and Searching With Array Controllers

Hi,

The Ember.SortableMixin faculty is built into Array controller.

It gives us a way to use 2 properties to control the activity of the sorting engine on the 'content' property.

App.GoodiesController = Ember.ArrayController.extend
  sortProperties:["name"]
  sortAscending: true

At this point - the 'content' or 'model' property now is sorted according to the ArrayController
and if you are looping over #each without any argument you get the benefits right away.

But what if you need to use the sorted content as input into another mechanism - say search results?

Let's say that you have set up a search field named 'searchText' in the bakery template
and you are using the observer pattern to get access to the field and then filtering based
on the searchText.

The searchResults property is what we will be iterating over instead of 'model' or 'content'

  <script type="text/x-handlebars" id="bakery">
At {{#link-to 'goodies' name}}"{{name}}" {{/link-to}}
    <br/>
    {{input type='text' value=searchText}}
    <!-- outlet is where goodies will appear (render) -->
    {{outlet}}
  </script>

  <script type="text/x-handlebars" id="goodies">
    You see the following goodies:
    <ul>
    {{#each item in searchResults}}
      <li>{{item.name}}</li>
    {{/each}}
    </ul>
  </script>

You have set up your controller to need the bakery searchText and are observing changes
to it - as well as filtering results from 'content' into 'searchResults'

searchResults begins life as a computed property defaultingTo 'content'

App.GoodiesController = Ember.ArrayController.extend({
  sortProperties:["name"],
  sortAscending: true,

  needs: "bakery",

  searchResults: Ember.computed.defaultTo("content"),

  filterItem: function (model) {
    searchInput = this.get('controllers.bakery.searchText')
    regexp = new RegExp(searchInput, "i");
    if(!searchInput || (searchInput && (0 == searchInput.length))) {
      return true
    } else if (-1 != model.name.search(regexp)) {
      return true
    } else {
      return false
    }
  },

  searchFilter: function() {
    searchInput = this.get('controllers.bakery.searchText')
    Ember.Logger.debug("someone is looking for " + this.get("controllers.bakery.searchText"))
    this.set('searchResults',this.get('content').filter(this.filterItem.bind(this)))
  }.observes("controllers.bakery.searchText"),
})

This gives you the ability to filter by results ... but now the sorting is not working.

This is where the property 'arrangedContent' of Ember.SortableMixin comes in handy.

by changing two lines to use 'arrangedContent' instead of 'content' you end up with both searching and sorting

App.GoodiesController = Ember.ArrayController.extend({
  sortProperties:["name"],
  sortAscending: true,

  needs: "bakery",

  // search on the sorted 
  searchResults: Ember.computed.defaultTo("arrangedContent"),

  filterItem: function (model) {
    searchInput = this.get('controllers.bakery.searchText')
    regexp = new RegExp(searchInput, "i");
    if(!searchInput || (searchInput && (0 == searchInput.length))) {
      return true
    } else if (-1 != model.name.search(regexp)) {
      return true
    } else {
      return false
    }
  },

  searchFilter: function() {
    searchInput = this.get('controllers.bakery.searchText')
    Ember.Logger.debug("someone is looking for " + this.get("controllers.bakery.searchText"))

   // search on the sorted
    this.set('searchResults',this.get('arrangedContent').filter(this.filterItem.bind(this)))

  }.observes("controllers.bakery.searchText"),
})

There you have it - chaining sorting and searching together.

Say Thanks
Respond

1 Response
Add your response

16047
D8537a5c77a809e0c818e5a24631c9ea

Perfect! I had no idea about this mystical arrangedContent property. Exactly what I needed, thanks a lot.

over 1 year ago ·