tennantje
tennantje

Reputation: 256

Emberjs - looping through an array 'each', but performing a different action every three objects

When using bootstrap + emberjs, I want to create a new <div class="row"> for every three objects in an array.

This is how I solved the same problem using Ruby+Rails.

<% @movies.in_groups_of(3) do |group| %>
    <div class="row">
    <% group.each do |movie| %>
         <div class="col-md-4">
             <h3><%= movie.title</h3>
             <%= image_tag(movie.thumb_url) %>
         </div>
     <% end %>
     </div>
<% end %>

I'm not sure (and am looking for help) on what "the ember way" of dealing with this is, obviously the below code results in a new row each time this loop completes - which is not the desired outcome.

{{#each model as |movie|}}
  <div class="row">
    <div class="col-md-4">
      <h3>{{movie.title}}</h3>
      <strong>Category Name</strong>
      <img width="100%" src="{{movie.thumb_url}}" alt="" />
    </div>
  </div>
{{/each}}

Assistance greatly appreciated - thanks!

Upvotes: 0

Views: 586

Answers (1)

maffews
maffews

Reputation: 525

See this ember-twiddle for working examples of both solutions in this answer.

You can use a modulo helper and the index parameter of {{#each}} to do something every n elements, but that won't be able to produce the structure you want because all elements in {{if}} blocks must be closed.

If you don't need to wrap the groups of three elements in a parent element, this will work:

app/helpers/mod.js

export function mod(params/*, hash*/) {
  return params[0] % params[1] == params[2];
}

export default Ember.Helper.helper(mod);

app/templates/application.hbs

{{#each elements as |el idx|}}
  <p>{{el}} {{if (mod idx 3 2) "3rd!"}}</p>
{{/each}}

However, if you want to wrap every three elements in a parent, you'll need to create a computed property that groups the elements for you:

app/controllers/application.js

export default Ember.Controller.extend({
  elements: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'i'],
  elementsInThrees: Ember.computed('elements', function () {
    var elementsInThrees = [];
    var currentGroup = [];
    this.get('elements').forEach((el, idx) => {
      if (idx % 3 == 0) {
        if (currentGroup.length) {
          elementsInThrees.push(currentGroup);
        }
        currentGroup = [];
      }
      currentGroup.push(el);
    });
    if (currentGroup.length) {
      elementsInThrees.push(currentGroup);
    }
    return elementsInThrees;
  }),
});

app/templates/application.hbs

<table>
  {{#each elementsInThrees as |elGroup|}}
    <tr>
      {{#each elGroup as |el|}}
        <td>{{el}}</td>
      {{/each}}
    </tr>
  {{/each}}
</table>

Upvotes: 1

Related Questions