Say I have an array like:
var values = [
Ember.Object.create({id: 1, name: 'One'}),
Ember.Object.create({id: 2, name: 'Two'}),
Ember.Object.create({id: 3, name: 'Three'})
];
I would like to create a sentence that links to each of the different objects. The output would generate something like:
{{link-to 'One' 'my-route' 1}}, {{link-to 'Two' 'my-route' 2}}, and {{link-to 'Three' 'my-route' 3}}
which would output a sentence, where each of the words links to a different route:
One, Two, and Three
Is it possible to do this dynamically? I know how to create a dynamic list of links if I'm just iterating over the array (see example):
{{#each item in values}}
<li>{{link-to item.name 'my-route' item.id}}</li>
{{/each}}
But this doesn't give me the flexibility to create a comma-separated list with 'and' at the end.
I'd create a computed property to give a bit of extra information. Assuming that values is a property on a controller:
listValues: function() {
return this.get('values').map(function(item, index, array) {
return {
item: item,
isLastItem: index === array.length - 1
};
});
}.property('values.[]')
Then, in your template:
{{#each listValues}}
{{#if isLastItem}}
and <li>{{link-to item 'my-route' item.id}}</li>
{{else}}
{{! Notice the trailing comma }}
<li>{{link-to item 'my-route' item.id}}</li>,
{{/if}}
{{/each}}
It's a bit of a hack, but you can create a computed property which is all your items except for the last item, and another computed property to return the last item.
Then, in your code you #each through all items but the last one, and then do and {{lastItem}}. For example:
{{#each item in allButLast}}
{{link-to item.name 'test' item.id}},
{{/each}}
and {{link-to lastItem.name 'test' lastItem.id}}
Here is a jsbin as an example.
Related
I have a an array coming from my model..
[
{id: 1, name: 'test1', created: true},
{id: 2, name: 'test2', created: false},
{id: 3, name: 'test3', created: true}
]
I am interested showing two lists. I created a component to show the list:
../components/created.hbs
<div>
{{model.name}}
</div>
../main.hbs
<h2> Created true </h2>
{{#each}}
{{created model=model }}
{{/each}}
<h2> Created false </h2>
{{#each}}
{{created model=model }}
{{/each}}
The first list would show the the objects with the created property set to true and the second would show those with the created property set to false.
I was wondering if there was a simple way of doing the above in Ember as in Angular where you could use filter pipes inside the each block.
each syntax in ember.js:
{{#each list as |item|}}
do what you want with item...
{{/each}}
First option:
So you can write a helper named filterBy, than use it:
{{#each (filterBy list key value) as |item|}}
do what you want with item...
{{/each}}
Second option:
You can write a computed property named filteredList in your component that uses Ember.computed.filterBy :
{{#each filteredList as |item|}}
do what you want with item...
{{/each}}
Both is acceptable for ember.js. I generally prefer second one as it has the filtering function in the component and doesn't need another dependency.
How would I do the following with Ember
My model is as follows
var model = [
{name: "a", type="letter"},
{name: "2", type="number"},
{name: "orange", type="fruit"}
]
{{#each item in model}}
{{#if item.type == "fruit"}}
<div>The item in this model matches fruit {{item.name}}</div>
{{/if}}
{{/each}}
How would I display a div with this message ONLY if the model instance type equals fruit?
You can use ember-truth-helpers. Your code would look like this:
{{#each item in model}}
{{#if (eq item.type "fruit")}}
<div>The item in this model matches fruit {{item.name}}</div>
{{/if}}
{{/each}}
It is trivial to write your own helper if you just want equality and/or don't want the extra dependency:
// app/helpers/eq.js
// for ember-cli with ember.js >=1.13
export default function(lhs, rhs) {
return lhs === rhs;
}
I have a Todo-App and now I want to add a list of checkboxes after each task.
When I click a checkbox the correct array item is changed but it's not updated in the template. Furthermore the checkboxes are always filled, even though the value when created is set to false.
I created an array attribute in the DS.Model with DS.Transform for that.
Todos.Todo = DS.Model.extend({
title: DS.attr('string'),
quarters: DS.attr('array')
});
Template:
{{#each item in quarters}}
<input type="checkbox" checked=item {{action "checkIndex" _view.contentIndex on="click"}}>
{{/each}}
_
Todos.TodoController = Ember.ObjectController.extend({
actions: {
checkIndex: function (index) {
var quarters = this.get('model.quarters');
var value = quarters[index];
value = value ? false : true;
var strIndex = '' + index;
quarters.set(strIndex, value);
console.log(this.get('model.quarters')[index]); // --> returns updated value
this.get('model').save();
}
....
It seems like I cannot iterate over the array attribute and render each item seperatly while keeping them updated. I searched a lot for solutions but still didn't figure it out. Or is there a better way to do this?
Iterating over array --> item gets not updated in template:
{{#each item in quarters}}
{{item}}
{{/each}}
Array --> get's updated in template:
{{quarters}}
JsFiddle: http://jsfiddle.net/Ld7gf/5/
Im having problems with letting hbs know that a property has changed.
Ive tried "propertyDidchange" etc. Nothing seems to be working.
I've a form counter
personFormCount: [{id: 1}, {id: 2}]
And form hbs
{{#each personFormCount}}
<br>Form ID: {{id}}
<button type="submit" {{action 'getID' id}}>ID</button> // sends ID
{{view 'person'}}
{{/each}}
JS
getID: function(id){
var index = id - 1;
this.get('personFormCount').splice(index, 1);
this.notifyPropertyChange('personFormCount');
},
No changes happening on template. Array changes itself properly when action triggered. Function should take care of deleting.
splice does change the array, but Ember isn't watching to see if you're splicing the array or not. You'll really want to use the built in remove functions.
http://emberjs.com/api/classes/Ember.ArrayProxy.html#method_removeObjects
http://emberjs.com/api/classes/Ember.ArrayProxy.html#method_removeObject
http://emberjs.com/api/classes/Ember.ArrayProxy.html#method_removeAt
In your case this would be a good implementation
{{#each personFormCount}}
<br>Form ID: {{id}}
<button type="submit" {{action 'removeItem' this}}>ID</button> // removes this item
{{view 'person'}}
{{/each}}
removeItem: function(item){
this.get('personFormCount').removeObject(item);
},
In my view I wanted to mockup a collection of featured items.
I want to do something like
{{#each featuredItems}}
{{title}}
{{/each}}
in my controller I have
App.ItemsController = Ember.ArrayController.extend
featuredApps = [
title: 'hi'
,
title: 'Ok'
,
title: "Three"
]
How do I iterate over this simply in my view? Right now I get this error:
Assertion failed: Expected hash or Mixin instance, got [object Array]
If I don't do it that way, then how would I do it if I added a feature flag to the Todo fixtures and wanted to iterate over a collection in the todos.hbs file specifically for featured and then below that show all of them?
Basically how do I do this
{{#each featured}}
{{title}}
{{/each}}
{{#each}}
{{title}}
{{/each}}
That puts the featured ones on the top and then everything all together in the bottom.
Maybe you can use an if statement to check if an item is featured or not and then display it. Something like this:
<ul>
{{#each item in model}}
{{#if item.featured}}
<h1>{{item.color}}</h1>
{{/if}}
{{/each}}
</ul>
You can check this jsBin:
http://emberjs.jsbin.com/OTotazu/2/edit