Showing filtered content on the index route


#1

Hey there, I’m still pretty new to Ember, and attempting to get some of the basics down when it comes to how to structure an application. I’m working on a sample app that’ll be used to teach people Ember, so I want to make sure I’m going down the right path though!

Here’s the rundown: On the index route for this site, we’re displaying the number of products (Product model, using fixtures) in the system. We’re also display 3 products that are onSale.

There are also routes for products and product which are straightforward enough – master/detail view, so no concerns there. The question is how to structure things for the index route.

Here’s what I have so far:

App.IndexRoute = Ember.Route.extend({
  model: function() {
    return this.store.findAll('product');
  }
});

App.IndexController = Ember.ArrayController.extend({
  onSale: function() {
    return this.filterProperty('isOnSale', true).slice(0,3);
  }.property('@each.isOnSale'),

  productCount: function() {
    return this.get('length');
  }.property('length')
});

Few questions on this:

  1. It feels a bit dirty to be fetching all products here, as well as in the products route. Would using modelFor here and having the products route be the main location that stores all products be a better convention? Would that run into any loading issues?
  2. Should the route be doing the filtering rather than the controller? It seems like if this was hitting a real API, the filtering would be done on the server and the model would just be an array of 3 products that are on sale.
  3. These two properties – an array of products on sale and the number of total products – seem to be too different to be in the same controller. Wondering if it makes sense to split this out of the index route altogether. I’m not sure what that would look like though. An OnSaleProductsController that is rendered in the index template maybe? Anything stand out for that situation?

I’m probably overthinking this a bit, as it does work fine now. Any advice or comments on this setup would be very much appreciated.

Thanks!


#2

Good questions, see my answers below.

You could only use modelFor to fetch the model for a parent route. So you could fetch all products in the ApplicationRoute and use this.modelFor('application') in your ProductsRoute but not the other way around.

It’s okay for the controller to do the filtering. Since you also need the (number of) products in the same template, you can’t just return the 3 products from the backend that are on sale, you need all of them.

If I understand you correctly, then the suggested onsale page would not be different than the current index page so I would not use a separate route (and thus controller). You can, however, use the render helper to render the onsale template and then you would have a separate OnSaleController. In fact, I would probably do that.

A couple of more comments:

  • filterProperty is now deprecated and true is the default second arg, so you could write this:
onSale: function() {
    return this.filterBy('isOnSale').slice(0,3);
}.property('@each.isOnSale'),
  • You can use a computed macro to implement productCount which is less error-prone and more succinct:
productCount: Ember.computed.alias('length')

These opinions are mine and I would be curious to see what others think. Hope that helps.


#3

Awesome feedback! It helped out a ton for sure.