Skip to content

Instantly share code, notes, and snippets.

@givanse
Last active March 10, 2017 05:15
Show Gist options
  • Save givanse/c580593125450d241f248d63193d6431 to your computer and use it in GitHub Desktop.
Save givanse/c580593125450d241f248d63193d6431 to your computer and use it in GitHub Desktop.
@each two levels deep is not supported
import Ember from 'ember';
function emberFruit(name, price, color) {
let fruit = {
name: name,
price: price,
attrs: {color: color}
};
return Ember.Object.create(fruit);
}
export default Ember.Controller.extend({
fruits: [
emberFruit('grape', 4, 'purple'),
emberFruit('watermelon', 6, 'yellow')
],
fruitNames: Ember.computed('fruits.[]', function() {
console.log('fruits.[]');
return this.get('fruits');
}),
fruitPrices: Ember.computed('[email protected]', function() {
console.log('[email protected]');
return this.get('fruits').map(function(fruit) {
return fruit.price;
});
}),
/*
* @each works only one level deep
*
* It won't recompute when the color property changes.
* (click `paint it black`)
*
* This computed will still trigger when elements
* are added or removed in the fruits list.
* (click `add apple`)
*
* Documentation:
* https://guides.emberjs.com/v2.2.0/object-model/computed-properties-and-aggregate-data/
*
* Github issue:
* Cannot observe changes to nested properties on array using @each
* https://github.com/emberjs/ember.js/issues/541
*/
fruitColors: Ember.computed('[email protected]', function() {
console.log('[email protected]');
return this.get('fruits').map(function(fruit) {
return fruit.attrs.color;
});
}),
fruitsAttrs: Ember.computed.mapBy('fruits', 'attrs'),
fruitColors2: Ember.computed('[email protected]', function() {
console.log('fruitColor2');
return this.get('fruitsAttrs').map(function(attr) {
return attr.color;
});
}),
actions: {
addApple: function() {
let apple = emberFruit('apple', 2, 'red');
this.get('fruits').addObject(apple);
},
upPrices: function() {
let fruits = this.get('fruits');
fruits.forEach(function(fruit) {
let p = fruit.get('price');
fruit.set('price', p + 1);
});
},
paintItBlack: function() {
let fruits = this.get('fruits');
fruits.forEach(function(fruit) {
fruit.set('attrs.color', 'black');
});
}
}
});
body {
margin: 12px 16px;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
font-size: 12pt;
}
.table {
display: flex;
flex-direction: row;
}
.col {
margin: 2px;
}
<h1>@each two levels deep is not supported</h1>
<p>
Note how the third column doesn't update after clicking <b>change color for all</b>.
</p>
<div class="table">
<div class="col">
name
<hr>
{{#each fruitNames as |fruit|}}
{{fruit.name}}
<br>
{{/each}}
</div>
<div class="col">
prices
<hr>
{{#each fruitPrices as |price|}}
{{price}}
<br>
{{/each}}
</div>
<div class="col">
@each nested prop
<hr>
{{#each fruitColors as |color|}}
{{color}}
<br>
{{/each}}
</div>
<div class="col">
fruitColors2
<hr>
{{#each fruitColors2 as |color|}}
{{color}}
<br>
{{/each}}
</div>
</div>
<br><br>
<button {{action "addApple"}}>add apple</button>
<button {{action "upPrices"}}>prices up</button>
<button {{action "paintItBlack"}}>change color for all</button>
<br><br>
<!-- Of course the underlying list is always updated with each button click. -->
fruits list raw:
<br><br>
{{#each fruits as |fruit|}}
{{fruit.name}} {{fruit.price}} {{fruit.attrs.color}}
<br>
{{/each}}
{{outlet}}
<br>
<br>
{
"version": "0.10.4",
"EmberENV": {
"FEATURES": {}
},
"options": {
"use_pods": false,
"enable-testing": false
},
"dependencies": {
"jquery": "https://cdnjs.cloudflare.com/ajax/libs/jquery/1.11.3/jquery.js",
"ember": "2.2.2",
"ember-data": "2.7.0",
"ember-template-compiler": "2.2.2"
},
"addons": {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment