Convert ArrayController with item controller having computed properties


#1

I try to convert Ember.js Web Development with Ember CLI ch5 example 1 to be Ember 2.0 ready by removing deprecations warning about ArrayController, but really don’t know how to rewrite ArrayController with itemController case.

template products.hbs as below, if I just change ArrayController -> Controller, model.name is still can accessible, but how to handle the itemController?

{{#each product in controller}}
<tr>
    <td>{{product.model.name}}</td>
    <td>{{product.shortDescription}}</td>
    <td>{{product.formattedDimension}}</td>
    <td>{{product.formattedPrice}}</td>
</tr>
{{/each}}

#2

You could use Ember Component instead of itemController and this will be near drop-in replacement, but with some minor modifications. The main point is that component takes care of each object inside your model instead of itemController and can be reused wherever needed.

Okay, let’s create an Ember Component first. Here we are defining a product property where we will store an instance of product passed down to the component from the model.

// components/x-product.js
export default Ember.Component.extend({
  product: null
});

Next, define a component template that will be rendered inside products template. Here we display the needed properties of product object.

// templates/components/x-product.hbs
<tr class="product">
  <td>{{product.name}}</td>
  <td>{{product.description}}</td>
  <td>{{product.currency}}</td>
</tr>

Then you would iterate over the model in your products template and assign each item inside model to the component’s product property.

// templates/products.hbs
{{#each model as |product|}}
  {{x-product product=product}}
{{/each}}

I checked it before posting so this works fine. To customize this solution to your own needs, just add computed properties to the component from your itemController file and edit component handlebars template to display those properties as you like. Pay attention to also change all mentions to the model property by swapping it with product property, like this:

formattedPrice: function(){
  return this.get('product.symbol') + "   " + Ember.$.number(this.get('product.price'),2);
}.property('product.symbol','product.price'),

Note, that in Ember 2.0 I would use new #each-in helper to iterate over product object properties in component template because it really simplifies the template if you want to display all the properties of the object, like this:

{{#each-in product as |key value|}}
  <p>{{key}}: {{value}}</p>
{{/each}

#3

Really appreciate your guide, seems still long journey to go in Ember way for me, thanks again.