I'm trying to take a collection of records in Ember and split them into groups of some number, say 2.
So for example, with something like
{{#each node in model}}
<span>node.name</span>
{{/each}}
I get <span>thing</span><span>other thing</span><span>some thing</span><span>one more thing</span>
I want to be able to pass node to something and wrap every 2 nodes with a div
something like <div><span>thing</span><span>other thing</span></div><div><span>some thing</span><span>one more thing</span></div>
In Ember 2.0 where most everything should be a component, where is the best place to handle this logic. Should it be a component or controller?
Given the principle that things related to display, or preparations therefor, belong in the component, I would prefer the component. You could do it like so:
partitions: computedPartition('model', 2)
Then in your template
{{#each partition in partitions}}
<div>
{{#each node in partition}}
{{node.name}}
{{/each}}
</div>
{{/each}}
Now it remains to write computedPartition
, which is an Ember computed property:
function computedPartition(dependentKey, size) {
return Ember.computed(dependentKey + ".@each", function() {
return partition(this.get(dependentKey), size);
});
}
There are different algorithms for partitioning. See this question. Here's a short recursive one:
function partition(array, n) {
array = array.slice();
return function _partition() {
return array.length ? [array.splice(0, n)].concat(_partition()) : [];
}();
}
We can simplify (?) the above by introducing a higher-level computed property called computedArrayInvoke
, which invokes a specified function on the array-valued property with the specified key, along with additional arguments:
function computedArrayInvoke(fn, dependentKey, ...args) {
return Ember.computed(dependentKey + ".@each", function() {
return fn(this.get(dependentKey), ...args);
});
}
Now we can write
partitions: computedArrayInvoke(partition, 'model', 2)