Limiting the number of elements displayed in a Ember Component

EmberIn Ember, if you had a List of People component and wanted to display only the top number of elements in a summary, and then link to somewhere else the full list but didn’t want to reimplement the component?

Normally you would have a people-list component template defined like

1
2
3
{{#each people as |person|}}
  {{person.body}}
{{/each}}

and you invoke it like:

1
{{people-list people=model}}

So, how to optionally limit the number of elements, without hardcoding that number?

So the first part is to pass in a property (showOnly) it to make available to a component, like this:

1
{{people-list showOnly=5 people=model}}

now you could limit the output but filtering the processing inside the #each loop (using the ember-truth-helpers add-on)

1
2
3
4
5
{{#each people as |person index|}}
   {{#if (lt index showOnly}}
     {{person.body}}
   {{/if}}
{{/each}}

So this sorta, kinda works. Using a computed property you can clean it up, like setting showOnly to people.length if no showOnly is set when the component is called. But I wasn’t happy. It looked very messy. And hard to use. My bigger concern was that the #each will still iterate over the full array. That didn’t seem very efficient!

So what is the alternate? How about resizing the people array to the requested size! In short, in the component class use .slice on the people array to make a shallow copy of a portion of an array into a new array object now of the requested size, if asked, like this:

1
2
3
4
5
6
7
8
9
10
import Ember from 'ember';
export default Ember.Component.extend({
 init() {
  this._super(...arguments);
  const showOnly = this.get('showOnly');
  if (showOnly && Number.isInteger( parseInt(showOnly))) {
   this.set('people', this.get('people').slice(0, parseInt(showOnly)));
  }
 }
});

Whats happening? I test that showOnly is present and a valid integer, then slice the people array to the requested size.

Also, if you did showOnly=”5″,

1
{{people-list showOnly="5" people=model}}

then parseInt will parse the string into a integer.

The extra bonus is that the component template is the original vanilla version, and if you called it without the showOnly property, or with a value it can’t understand, it would work as expected with no muss, no fuss!

1
2
3
{{#each people as |person|}}
  {{person.body}}
{{/each}}

And there we have it.

a version is on ember-twiddle and gist for you to gawk at.

I wonder what other smart and unobtrusive customizations can be applied to my components? hummm :\ (Many thanks to the ember slack community, and spikedkira in particular.

Leave a Reply