0
votes

I have a model:

export default DS.Model.extend({
  name: DS.attr('string'),
  things: DS.hasMany('match', {async: true, defaultValue: []})
});

I can iterate through the things in a template:

{{#each model.things as |thing|}}
    <h3>thing.title</h3>
{{/each}}

But I don't want all of the things. I only want to display some of them. And which I will display will depend on a controller variable. So my thought is that I would have a computed property in the controller, as follows:

export default Ember.Controller.extend({
  state: 0,
  displayThings: function() {
    var things = this.get('model').things;
    var state = this.get('state');
    // do stuff, filter in a way that isn't important
    return things;
  }.property('state')
});

Forgetting the filtering for now, if I try to iterate through these displayThings as follows:

{{#each displayThings as |thing|}}
    <h3>thing.title</h3>
{{/each}}

Nothing shows up in the template. I can verify with console.log that the things are in the controller property, and some object is getting sent to the template, but not an object that can be iterated, somehow.

I'm using Ember 1.13.

1
Don't you want this.get('model.things')? By the way, the default value for things is unnecessary. Also, realize your displayThings computed property is returning things. Don't you want it to return some filtered version of things instead? - user663031

1 Answers

0
votes

The key part of filtering is not included in your code, and there might lie the reason why what you're getting returned from displayThings is not iterable or something. Also, as @torazaburo points out in a comment to your question, you're returning things, and you might want to return a filtered version of things.

And lastly, and very important, your displayThings property should depend not only on state, but also on model.things or some variation of it, depending on the actual filtering. For instance, if you're filtering the things collection by a specific field status, then displayThings should also have a dependency declared like shown below:

displayThings: Ember.computed('state', '[email protected]', function() {
  // ...
})

If your filtering condition is more complex than just depending on one or two fields of the collection's items, then maybe you can declare dependency on the whole collection objects, like this:

displayThings: Ember.computed('state', 'model.things.[]', function() {
  // ...
})

The code above states that if the things collection changes, or any of the objects in it change in any way, then the displayThings property is re-computed.

Now, back to your original question, I'll give it a crack by posting here a complete version of your controller code with an actual hypothetical filtering being done. Perhaps you could apply your actual filtering criteria by modifying this code:

export default Ember.Controller.extend({
  state: 0,
  displayThings: Ember.computed('state', '[email protected]', function() {
    var state = this.get('state');
    return this.get('model.things').filter(function(thing) {
      return thing.get('status') > state;
    });
  })
});

The above controller will expose in displayThings a collection of all things whose status is strictly greater than the controller's state property. This should do the trick, and should be easily adapted to some other filtering criteria by changing the filtering function, and updating the dependency declaration correspondingly, as explained above.