Search code examples
javascriptruby-on-railsember.jstemplate-enginehandlebars.js

Emberjs, each block helper advanced


This is my flat model:

 [
    { id: 1, title: '', body: '' },
    { id: 2, title: '', body: '' },
    { id: 3, title: '', body: '' },
    { id: 4, title: '', body: '' },
    // ...
 ]

This is my expected template:

  <div class="row">
    <div class="col-md-4 col-md-offset-2">
      <h6>{{! item1 title }}</h6>
      <p>{{! item1 body}}</p>
    </div>
    <div class="col-md-4 col-md-offset-1">
      <h6>{{! item2 title}}</h6>
      <p>{{! item2 body}}</p>
    </div>
  </div>
  <div class="row">
    <div class="col-md-4 col-md-offset-2">
      <h6>{{! item3 title }}</h6>
      <p>{{! item3 body}}</p>
    </div>
    <div class="col-md-4 col-md-offset-1">
      <h6>{{! item4 title}}</h6>
      <p>{{! item4 body}}</p>
    </div>
  </div>
  <!-- ... -->

What is the ember approach to do this?

A simple each helper won't help because template combines two elements from the model.

Should I change my model, customize an array controller, build a component, write a template helper, or is there a built in solution for this simple problem?


Solution

  • You should change your data structure. I'd still use an ArrayController, but at the same time I'd add a computed property on it that grouped everything up (I'm guessing your pattern is every other).

    App.FooController = Em.ArrayController.extend({
      groupedItems: function(){
        var groups = [],
            group,
            model = this.get('model'),
            len = this.get('length');
        for(var i = 0;i<len;i++){
          if(i%2==0){
            group = [];
            groups.push(group);
          }
          group.push(model[i]);
        }
        return groups;
      }.property('model.[]')
    });
    
    {{#each item in groupedItems}}
      <div class="row">
        <div class="col-md-4 col-md-offset-2">
          <h6>{{ item.firstObject.title }}</h6>
          <p>{{ item.firstObject.body}}</p>
        </div>
        <div class="col-md-4 col-md-offset-1">
          <h6>{{item.lastObject.title}}</h6>
          <p>{{item.lastObject.body}}</p>
        </div>
      </div>
    {{/each}} 
    

    Honestly, there are a slew of ways of grouping them, the point I'm trying to make is grouping would be the simplest.