Eike Cochu
Eike Cochu

Reputation: 3429

Ember: filter model by text field

I want to filter a model by a text field, the filter should be applied as the user types. I am coming from angular (not a pro but I managed to create such a filter there), so I expected this to be easy. Heh.

list.hbs:

{{input type='text' placeholder='Filter' size='50' valueBinding='searchKeyword'}}

<ol>
  {{#each model.articles as |article|}}
    <li>{{{article.title}}</li>
  {{/each}}
</ol>

I know that this question is asked a lot and I did a lot of research before I decided that the amout of searching is inappropriate for such a problem and that I do not understand some core ideas of ember. It seems like that with the transition from 1.x to 2.x most examples, questions and guides are invalid. My question has been asked multiple times already:

EmberJS filter array of items as the user types

text field filtering a list using ember + ember data

Emberjs - Connecting an {{ input }} filter bar with my list of Objects. As I type, the list filters

but all of the answers use controllers. The docs say that "controllers will be replaced with components". So... how to filter a model the new way?

--

UPDATE

I used Remi's example to create this component:

export default Ember.Component.extend({

  filteredArticles: Ember.computed('articles', 'filter', function() {
    var keyword = this.get('filter');
    var filtered = this.get('articles');
    if (keyword) {
      keyword = keyword.toLowerCase().trim();
      filtered = this.get('articles').filter((item) => item.get('title').toLowerCase().includes(keyword));
    }
    return filtered;
  })

});

the computed property is used as the {{#each filteredArticles... argument and setting a property beforehand (which raised a deprecation warning) is not required anymore.

Upvotes: 1

Views: 1300

Answers (1)

Remi Smirra
Remi Smirra

Reputation: 2539

Components act pretty similar to controllers in some ways. You can think of them as a combination of controller+view in older ember versions. They still work in current ember. But if you want to make your issue work via components, I would suggest the following:

Lest say, you have a /templates/components/list.hbs:

{{input type='text' placeholder='Filter' size='50' valueBinding='searchKeyword'}}

<ol>
  {{#each filteredArticles as |article|}}
    <li>{{{article.title}}</li>
  {{/each}}
</ol>

In one of your templates that should use the components, e.g. /templates/my-list.hbs:

{{list articles=model.articles}}

Then for your component to work, add a /components/list.js:

Ember.Component.extend({
    searchKeyword: null,
    articles: null,
    filteredArticles: null,
    updateList: Ember.computed('searchKeyword', function(){
        var keyword = this.get('searchKeyword');

        var filtered = this.get('articles').filterBy('title', searchKeyword);
        this.set('filteredArticles', filtered);     
    }),
    didInsertElement(){
       this.set('filteredArticles', this.get('articles'));
    }
})

Upvotes: 1

Related Questions