Emberjs - Connecting an {{ input }} filter bar wit

2019-02-20 05:45发布

问题:

I am trying to incorporate this working example http://jsbin.com/AViZATE/37/edit of a filtering search bar with my own project. The search bar does not seem to be connected to my list of objects. :(

Let me show you what I've done.

App.RecordCategoriesController = Ember.ArrayController.extend({
    searchResult: function(){
        var searchTerm = this.get('searchTerm');
        var regExp = new RegExp(searchTerm,'i');
        this.get('model').set('content',this.store.filter('recordCategory',function(item){
            return regExp.test(item.get('categoryName'));
        }));
    }.observes('searchTerm'),
});

As you can see above, I've replaced 'todo' with 'recordCategory' and 'title' with 'categoryName'. Seems good so far.'

In record_categories.hbs i've created the input bar that will be used to filter.

{{input type="text" id="search-todo" placeholder="Search Todo List..." value=searchTerm}}

and then below it, the #each handlebars to loop through and display my list

{{#each itemController="recordCategory"}}
  <li>{{categoryName}}</li>
{{/each}}

Am I missing something? I noticed that searchResults doesn't seem to be called anywhere else in their example

Also here is my route because why not.

App.RecordCategoriesRoute = Ember.Route.extend({     
    model: function() {
        VpcYeoman.RecordCategories.FIXTURES=[];
        $.ajax({
            url: '/recordCategories',
            dataType: 'json',
            type:"get",      
            async: false,
            success : function(data, textStatus, xhr) { 
                if(xhr.status==200){
                    VpcYeoman.RecordCategories.FIXTURES=data;
                }
            }
        });
        return this.store.find('recordCategories');
    }
}); 

回答1:

I'm going to try to mostly ignore the JSBin and look at what you have, as I think that will help you more. So if I miss something obvious from the JSBin, let me know.

First thing to notice is that, from your route, you return an array of objects. Ember would normally generate an ArrayController for you, but you've extended that yourself. And the thing that's special (and nice) about ArrayControllers is that their content is the array. So in your template, you could just do this:

{{#each}}
    {{categoryName}}
{{/each}}

And that would list all of the items that were returned from this.store.find('recordCategories').

But you want to filter your items, so that's no good. So let's move on to point two. The best way to filter a list of items is by using a read-only computed property. You definitely don't want to set the content of the model to the filtered items. You want the original items to remain intact, and the filter be just a certain way of looking at the original items. So, using a slightly modified example from here, let's do that.

App.RecordCategoriesController = Ember.ArrayController.extend({

    searchResults: function() {
        var searchTerm = this.get('searchTerm');
        var regExp = new RegExp(searchTerm,'i');

        // We use `this.filter` because the contents of `this` is an array of objects
        var filteredResults = this.filter(function(category) {
            return regExp.test(category.get('categoryName'));
        });

        return filteredResults;
    }.property('@each.categoryName', 'searchTerm')

});

So now you've got a computed property that filters the items in the array controller based on the search term. And because of its dependancies, it will re-caclulate anytime the items change or the search term changes. And this way, you didn't have to change any model values. Finally, you'd use it like this:

// record_categories.hbs

{{input type="text" id="search-todo" placeholder="Search Todo List..." value=searchTerm}}

{{#each searchResults}}
    {{categoryName}}
{{/each}}

And just to make sure that I wasn't completely BSing, I created a JSBin to show that it works.