-
-
Notifications
You must be signed in to change notification settings - Fork 4.2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[FEATURE array-helper] Implement array helper RFC #318
- Loading branch information
1 parent
7116215
commit 4ef1df2
Showing
3 changed files
with
276 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
import { Arguments, VM } from '@glimmer/runtime'; | ||
|
||
/** | ||
@module ember | ||
*/ | ||
|
||
/** | ||
Use the `{{array}}` helper to create an array to pass as an option to your | ||
components. | ||
```handlebars | ||
{{my-component people=(array | ||
'Tom Dade' | ||
'Yehuda Katz' | ||
this.myOtherPerson) | ||
}} | ||
``` | ||
Would result in an object such as: | ||
```js | ||
['Tom Date', 'Yehuda Katz', this.get('myOtherPerson')] | ||
``` | ||
Where the 3rd item in the array is bound to updates of the `myOtherPerson` property. | ||
@method array | ||
@for Ember.Templates.helpers | ||
@param {Array} options | ||
@return {Array} Array | ||
@category array-helper | ||
@since 2.7.0 | ||
@public | ||
*/ | ||
|
||
export default function(_vm: VM, args: Arguments) { | ||
return args.positional.capture(); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
236 changes: 236 additions & 0 deletions
236
packages/@ember/-internals/glimmer/tests/integration/helpers/array-test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,236 @@ | ||
import { RenderingTest, moduleFor } from '../../utils/test-case'; | ||
import { strip } from '../../utils/abstract-test-case'; | ||
import { Component } from '../../utils/helpers'; | ||
import { set } from '@ember/-internals/metal'; | ||
|
||
moduleFor( | ||
'Helpers test: {{array}}', | ||
class extends RenderingTest { | ||
['@test returns an array']() { | ||
this.render(strip`{{#with (array "Sergio") as |people|}} | ||
{{#each people as |personName|}} | ||
{{personName}} | ||
{{/each}} | ||
{{/with}}`); | ||
|
||
this.assertText('Sergio'); | ||
|
||
this.assertStableRerender(); | ||
} | ||
|
||
['@test can have more than one value']() { | ||
this.render(strip`{{#with (array "Sergio" "Robert") as |people|}} | ||
{{#each people as |personName|}} | ||
{{personName}}, | ||
{{/each}} | ||
{{/with}}`); | ||
|
||
this.assertText('Sergio,Robert,'); | ||
|
||
this.assertStableRerender(); | ||
} | ||
|
||
['@test binds values when variables are used']() { | ||
this.render( | ||
strip`{{#with (array personOne) as |people|}} | ||
{{#each people as |personName|}} | ||
{{personName}} | ||
{{/each}} | ||
{{/with}}`, | ||
{ | ||
personOne: 'Tom', | ||
} | ||
); | ||
|
||
this.assertText('Tom'); | ||
|
||
this.assertStableRerender(); | ||
|
||
this.runTask(() => set(this.context, 'personOne', 'Yehuda')); | ||
this.assertText('Yehuda'); | ||
} | ||
|
||
['@test binds multiple values when variables are used']() { | ||
this.render( | ||
strip`{{#with (array personOne personTwo) as |people|}} | ||
{{#each people as |personName|}} | ||
{{personName}}, | ||
{{/each}} | ||
{{/with}}`, | ||
{ | ||
personOne: 'Tom', | ||
personTwo: 'Yehuda', | ||
} | ||
); | ||
|
||
this.assertText('Tom,Yehuda,'); | ||
|
||
this.assertStableRerender(); | ||
|
||
this.runTask(() => set(this.context, 'personOne', 'Sergio')); | ||
|
||
this.assertText('Sergio,Yehuda,'); | ||
|
||
this.runTask(() => set(this.context, 'personTwo', 'Tom')); | ||
|
||
this.assertText('Sergio,Tom,'); | ||
} | ||
|
||
['@test array helpers can be nested']() { | ||
this.render( | ||
strip`{{#with (array (array personOne personTwo)) as |listOfPeople|}} | ||
{{#each listOfPeople as |people|}} | ||
List: | ||
{{#each people as |personName|}} | ||
{{personName}}, | ||
{{/each}} | ||
{{/each}} | ||
{{/with}}`, | ||
{ | ||
personOne: 'Tom', | ||
personTwo: 'Yehuda', | ||
} | ||
); | ||
|
||
this.assertText('List:Tom,Yehuda,'); | ||
|
||
this.assertStableRerender(); | ||
|
||
this.runTask(() => set(this.context, 'personOne', 'Chad')); | ||
|
||
this.assertText('List:Chad,Yehuda,'); | ||
|
||
this.runTask(() => set(this.context, 'personTwo', 'Balint')); | ||
|
||
this.assertText('List:Chad,Balint,'); | ||
} | ||
|
||
['@test should yield hash of an array of internal properties']() { | ||
let fooBarInstance; | ||
let FooBarComponent = Component.extend({ | ||
init() { | ||
this._super(); | ||
fooBarInstance = this; | ||
this.model = { personOne: 'Chad' }; | ||
}, | ||
}); | ||
|
||
this.registerComponent('foo-bar', { | ||
ComponentClass: FooBarComponent, | ||
template: `{{yield (hash people=(array model.personOne))}}`, | ||
}); | ||
|
||
this.render(strip`{{#foo-bar as |values|}} | ||
{{#each values.people as |personName|}} | ||
{{personName}} | ||
{{/each}} | ||
{{/foo-bar}}`); | ||
|
||
this.assertText('Chad'); | ||
|
||
this.assertStableRerender(); | ||
|
||
this.runTask(() => set(fooBarInstance, 'model.personOne', 'Godfrey')); | ||
|
||
this.assertText('Godfrey'); | ||
|
||
this.runTask(() => set(fooBarInstance, 'model', { personOne: 'Chad' })); | ||
|
||
this.assertText('Chad'); | ||
} | ||
|
||
['@test should yield hash of an array of internal and external properties']() { | ||
let fooBarInstance; | ||
let FooBarComponent = Component.extend({ | ||
init() { | ||
this._super(); | ||
fooBarInstance = this; | ||
this.model = { personOne: 'Chad' }; | ||
}, | ||
}); | ||
|
||
this.registerComponent('foo-bar', { | ||
ComponentClass: FooBarComponent, | ||
template: `{{yield (hash people=(array model.personOne personTwo))}}`, | ||
}); | ||
|
||
this.render( | ||
strip`{{#foo-bar personTwo=model.personTwo as |values|}} | ||
{{#each values.people as |personName|}} | ||
{{personName}}, | ||
{{/each}} | ||
{{/foo-bar}}`, | ||
{ | ||
model: { personTwo: 'Tom' }, | ||
} | ||
); | ||
|
||
this.assertText('Chad,Tom,'); | ||
|
||
this.assertStableRerender(); | ||
|
||
this.runTask(() => { | ||
set(fooBarInstance, 'model.personOne', 'Godfrey'); | ||
set(this.context, 'model.personTwo', 'Yehuda'); | ||
}); | ||
|
||
this.assertText('Godfrey,Yehuda,'); | ||
|
||
this.runTask(() => { | ||
set(fooBarInstance, 'model', { personOne: 'Chad' }); | ||
set(this.context, 'model', { personTwo: 'Tom' }); | ||
}); | ||
|
||
this.assertText('Chad,Tom,'); | ||
} | ||
|
||
['@test should render when passing as argument to a component invocation']() { | ||
let FooBarComponent = Component.extend({}); | ||
|
||
this.registerComponent('foo-bar', { | ||
ComponentClass: FooBarComponent, | ||
template: strip`{{#each people as |personName|}} | ||
{{personName}}, | ||
{{/each}}`, | ||
}); | ||
|
||
this.render(strip`{{foo-bar people=(array "Tom" personTwo)}}`, { personTwo: 'Chad' }); | ||
|
||
this.assertText('Tom,Chad,'); | ||
|
||
this.assertStableRerender(); | ||
|
||
this.runTask(() => set(this.context, 'personTwo', 'Godfrey')); | ||
|
||
this.assertText('Tom,Godfrey,'); | ||
} | ||
|
||
['@test should return an entirely new array when any argument change']() { | ||
let fooBarInstance; | ||
let FooBarComponent = Component.extend({ | ||
init() { | ||
this._super(); | ||
fooBarInstance = this; | ||
}, | ||
}); | ||
|
||
this.registerComponent('foo-bar', { | ||
ComponentClass: FooBarComponent, | ||
template: strip`{{#each people as |personName|}} | ||
{{personName}}, | ||
{{/each}}`, | ||
}); | ||
|
||
this.render(strip`{{foo-bar people=(array "Tom" personTwo)}}`, { personTwo: 'Chad' }); | ||
|
||
let firstArray = fooBarInstance.people; | ||
|
||
this.runTask(() => set(this.context, 'personTwo', 'Godfrey')); | ||
|
||
this.assert.ok( | ||
firstArray !== fooBarInstance.people, | ||
'should have created an entirely new array' | ||
); | ||
} | ||
} | ||
); |