Search code examples
ember.jsember-dataember-cli

Why doesn't the newly added item render in the template?


So far my groupedItems is rendered properly in the template. But when I click on the add to cart link, which triggers the addToCart action. The template does not render the new item... I have to manually refresh the page to see it.

I check Ember Inspector, Data tab. The newly added item was appended to the list. So, if reflects in the data store, shouldn't it reflect/render in the template as well?

The newly added item was also persisted in the database.

If I change my model hook in the routes to items: this.store.find('item'), instead of items: this.store.find('item', { status: 'queued' }). Everything works...

I suspect it is the way my computed property, groupedItems, is being managed. Any pointers?

// Routes
import Ember from 'ember';

export default Ember.Route.extend({
  model: function() {
    return Ember.RSVP.hash({
      // items: this.store.find('item'),
      // items: this.store.find('item').filterBy('status', 'queued'),
      items: this.store.find('item', { status: 'queued' }),
      // products: this.store.find('product', { status: 'available' })
    });
  },

  // You can use model.items to get items, etc
  // Since the model is a plain object you can just use setProperties
  // http://stackoverflow.com/questions/16463958/how-to-use-multiple-models-with-a-single-route-in-emberjs-ember-data
  setupController: function(controller, model) {
    // model.reload;
    controller.setProperties(model);
  },

  actions: {
    addToCart: function(product) {
      var _this = this;

      var item = _this.store.createRecord('item');
      item.set('product', product);

      item.save().then(function() {
        // _this.transitionTo(fromRoute);
      });
    }
  }
});

// Controller
import Ember from 'ember';

export default Ember.Controller.extend({
  groupedItems: function () {
    var result = [];

    this.get('items').forEach(function(item) {
    // this.get('items').filterBy('status', 'queued').forEach(function(item) {
      var hasProductId = result.findBy('productId', item.get('product.id'));

      if(!hasProductId) {
         result.pushObject(Ember.Object.create({
            productId:        item.get('product.id'),
            product:          item.get('product'),
            item:             item,
            numberOfProducts: 0,
            subtotalInCents:  0
         }));
      }

      var productFromResult = result.findBy('productId', item.get('product.id'));

      productFromResult.set('numberOfProducts', productFromResult.get('numberOfProducts') + 1);

      item.get('product').then(function(product){
        productFromResult.set('subtotalInCents', productFromResult.get('subtotalInCents') + product.get('amountInCents'));
      });
    });

    return result;
  }.property('items.@each')
});

// Template / hbs
<ul>
  {{#each groupedItems}}
    <li>
      <a href="#" {{action "addToCart" product}}>Add</a>
      / <a href="#" {{action "removeFromCart" item 'index'}}>Remove</a>
      {{numberOfProducts}} {{product.name}} P{{cents-to-pesos product.amountInCents}} / each
    </li>
  {{/each}}
</ul>

Solution

  • To have new records synced automatically you should use store.filter instead of store.find. Check out the ember docs for more details: http://emberjs.com/api/data/classes/DS.Store.html#method_filter