Skip to content

Commit

Permalink
[DOC] Minor fixes for {{#each}} and {{#each-in}}
Browse files Browse the repository at this point in the history
This is maybe part of #18363?

The `{{#each}}` docs is the only instance in the API docs where we reference
a `model` property. It's not even clear if this is referring to the
controller's property, but since it's just an arbitrary name for illustration
purposes, I just changed it to match the rest of the examples given in the
same block.

I also tried to make the `key` documentation a little more clear.
  • Loading branch information
chancancode authored Sep 7, 2019
1 parent d60cf69 commit 0118690
Showing 1 changed file with 49 additions and 25 deletions.
74 changes: 49 additions & 25 deletions packages/@ember/-internals/glimmer/lib/helpers/each-in.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,68 +9,92 @@ import { Opaque } from '@glimmer/util';
/**
The `{{#each}}` helper loops over elements in a collection. It is an extension
of the base Handlebars `{{#each}}` helper.
The default behavior of `{{#each}}` is to yield its inner block once for every
item in an array passing the item as the first block parameter.
Assuming the `@developers` argument contains this array:
```javascript
var developers = [{ name: 'Yehuda' },{ name: 'Tom' }, { name: 'Paul' }];
[{ name: 'Yehuda' },{ name: 'Tom' }, { name: 'Paul' }];
```
```handlebars
{{#each developers key="name" as |person|}}
{{#each @developers key="name" as |person|}}
{{person.name}}
{{! `this` is whatever it was outside the #each }}
{{/each}}
```
The same rules apply to arrays of primitives.
```javascript
var developerNames = ['Yehuda', 'Tom', 'Paul']
['Yehuda', 'Tom', 'Paul']
```
```handlebars
{{#each developerNames key="@index" as |name|}}
{{#each @developerNames key="@index" as |name|}}
{{name}}
{{/each}}
```
During iteration, the index of each item in the array is provided as a second block parameter.
During iteration, the index of each item in the array is provided as a second block
parameter.
```handlebars
<ul>
{{#each people as |person index|}}
{{#each @developers as |person index|}}
<li>Hello, {{person.name}}! You're number {{index}} in line</li>
{{/each}}
</ul>
```
### Specifying Keys
The `key` option is used to tell Ember how to determine if the array being
iterated over with `{{#each}}` has changed between renders. By helping Ember
detect that some elements in the array are the same, DOM elements can be
re-used, significantly improving rendering speed.
For example, here's the `{{#each}}` helper with its `key` set to `id`:
In order to improve rendering speed, Ember will try to reuse the DOM elements
where possible. Specifically, if the same item is present in the array both
before and after the change, its DOM output will be reused.
The `key` option is used to tell Ember how to determine if the items in the
array being iterated over with `{{#each}}` has changed between renders. By
default the item's object identity is used.
This is usually sufficient, so in most cases, the `key` option is simply not
needed. However, in some rare cases, the objects' identities may change even
though they represent the same underlying data.
For example:
```javascript
people.map(person => {
return { ...person, type: 'developer' };
});
```
In this case, each time the `people` array is `map`-ed over, it will produce
an new array with completely different objects between renders. In these cases,
you can help Ember determine how these objects related to each other with the
`key` option:
```handlebars
{{#each model key="id" as |item|}}
{{/each}}
<ul>
{{#each @developers key="name" as |person|}}
<li>Hello, {{person.name}}! You're number {{index}} in line</li>
{{/each}}
</ul>
```
When this `{{#each}}` re-renders, Ember will match up the previously rendered
items (and reorder the generated DOM elements) based on each item's `id`
property.
By default the item's own reference is used.
By doing so, Ember will use the value of the property specified (`person.name`
in the example) to find a "match" from the previous render. That is, if Ember
has previously seen an object from the `@developers` array with an matching
name, its DOM elements will be re-used.
### {{else}} condition
`{{#each}}` can have a matching `{{else}}`. The contents of this block will render
if the collection is empty.
```handlebars
{{#each developers as |person|}}
{{#each @developers as |person|}}
{{person.name}}
{{else}}
<p>Sorry, nobody is available for this task.</p>
Expand All @@ -85,7 +109,7 @@ import { Opaque } from '@glimmer/util';
/**
The `{{each-in}}` helper loops over properties on an object.
For example, given a `user` object that looks like:
For example, if the `@user` argument contains this object:
```javascript
{
Expand All @@ -94,12 +118,12 @@ import { Opaque } from '@glimmer/util';
}
```
This template would display all properties on the `user`
This template would display all properties on the `@user`
object in a list:
```handlebars
<ul>
{{#each-in user as |key value|}}
{{#each-in @user as |key value|}}
<li>{{key}}: {{value}}</li>
{{/each-in}}
</ul>
Expand Down

0 comments on commit 0118690

Please sign in to comment.