简体   繁体   中英

Returning a function error in Ember.js

I find this weird that whenever I am declaring variables in my controller and I want to return a filtered value from my model I have to use a function. But when I try to call it using {{#each}} it gives me an error.

Uncaught Error: Assertion Failed: The value that #each loops over must be an Array. You passed function () {
        return this.store.filter('entry', function(entry) {
            return (entry.get('entry_week') == moment().week());
        });
    } 

My Controller

App.CurrentWeekController = Ember.ArrayController.extend({
    current_week: function() {
        return this.store.filter('entry', function(entry) {
            return (entry.get('entry_week') == moment().week());
        });
    }   
});

EDIT: Route

App.CurrentWeekRoute = App.AuthenticatedRoute.extend({
    model: function() {
        return this.store.find('entry');
    },
    setupController: function(controller, entries) {
        controller.set('model', entries);
    }
});

handlebars

    {{#each current_week}}
        {{description}}
    {{/each}}

So what's a better approach? I essentially have a lots of model instances and I need to filter them by certain conditions and display them separately.

In any case, how can I have a controller variable contain a filtered set of my model instances.

You can empty your controller and then update your route to this:

App.CurrentWeekRoute = App.AuthenticatedRoute.extend({
    model: function() {
        var current_week = moment().week();
        return this.store.filter('entry', function(entry) {
            return entry.get('entry_week') == current_week;
        });
    }
});

Now, just because you have this code here does not mean that something will show up. Your filter may not be working as you expect.

You may want to do this in your hbs file:

{{#each current_week}}
  {{description}}
{{else}}
  <p>No entries this week.</p>
{{/each}}

You need to declare those functions as Computed Properties of the properties you are using to filter the items.

Additionally, you shouldn't have to use DS.Store#filter , but instead use Ember.Enumerable#filter on the App.CurrentWeekController model. The model property already contains a live collection of all your App.Entry records.

App.CurrentWeekController = Ember.ArrayController.extend({
    current_week: function() {
        return this.get('model').filter(function(entry) {
            return (entry.get('entry_week') == moment().week());
        });
    }.property('@each.entry_week')
});

One caveat is that the current_week array won't be updated on moment().week() change. You need some way of making sure current_week is recomputed when the week changes. Have a look at http://emberjs.com/guides/cookbook/working_with_objects/continuous_redrawing_of_views/ for some inspiration.

Alternative approach

Assuming your model is App.Entry , define an isCurrentWeek computed property in your model definition, and use it in your template to show only those.

App.Entry = DS.Model.extend({
  // ...

  isCurrentWeek: function() {
    return this.get('entry_week') == moment().week();
  }.property('entry_week')
});

And in your template:

{{#each}}
  {{#if isCurrentWeek}}
    {{description}}
  {{/if}}
{{/each}}

I wanna jump on the bandwagon of adding a million good answers :) I recommend using filterBy , quick and clean.

App.CurrentWeekController = Ember.ArrayController.extend({
    current_week: function() {
        return this.filterBy('entry', moment().week());
    }.property('@each.entry_week')
});

http://emberjs.jsbin.com/OxIDiVU/702/edit

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM