How to sort the model array before supply to template - ember.js

Here is my model, how can i sort it before I send to template?
route.js
import Ember from 'ember';
export default Ember.Route.extend({
model(){
return {
"fruits":[
{fruit:"mango",color:"yello"},
{fruit:"banana",color:"muddy yellow"},
{fruit:"apple",color:"red"}],
"prices":[9, 10,5 ]
}
}
});
Twiddle Demo
Any one please update my twiddle? looking for ember approch.
here is my hbs:
<h1>Fruit Prices Sorted here</h1>
<ul>
{{#each sortedSongs as |price|}}
<li> {{price.fruit}}</li>
{{/each}}
</ul>
<h1>Fruit Prices Sorted here</h1>
<ul>
{{#each sortedPrice as |price|}}
<li> {{price.price}}</li>
{{/each}}
</ul>
<h1>Fruit Details Sorted by Alphabetically </h1>
<ul>
{{#each model.fruits as |fruitObject|}}
<li> {{fruitObject.fruit}}</li>
{{/each}}
</ul>
<br>
<h1>Fruit Color Sorted by Alphabetically </h1>
<ul>
{{#each model.fruits as |fruitObject|}}
<li> {{fruitObject.color}}</li>
{{/each}}
</ul>

Take a look into Ember.computed.sort or
In your twiddle you should create a computed property in the controller, which would sort model.fruits and return the result, e.g.:
nameSort: ['name'],
sortedByName: Ember.computed.sort('model.fruits', 'nameSort')
The second argument has to be a name of a property which holds an array of properties you want to sort by. Or you can provide a function if you need some custom sorting logic.
I've edited your twiddle. Also I think the price attribute was supposed to go inside each fruit object, not in a separate list, so I moved it.
https://ember-twiddle.com/78e0b3e9ff873a8909221efc87e3ef43
Next time do some research though, Ember.computed.sort documentation isn't hard to find.

Related

Ember Octane - How to loop through model records inside a component?

I have an array of strings passed as an argument to a component, inside the component I am using "each" helper to render each string in a text input. I tried the following approach.
I have a model passed as an argument to a component. I'm using #each helper to iterate through that model and this does not work.
Example:
Template
<div>
<Location::LocationList #model="{{#model}}"/>
</div>
LocationList component:
<ul class="location-list">
{{#each this.args.model as |location|}}
<li>
{{#location.title}}
</li>
{{/each}}
</ul>
And if I just do it in this way:
<ul class="location-list">
{{#each #model as |location|}}
<li>
<Location::LocationItem #location={{location}}/>
</li>
{{/each}}
</ul>
It works as needed.
Any suggestions?
According to the docs on Component Arguments, using the #model as you have in your last snippet,
<ul class="location-list">
{{#each #model as |location|}}
<li>
<Location::LocationItem #location={{location}}/>
</li>
{{/each}}
</ul>
is the correct way to reference arguments.
Referencing args via this.args is reserved for usage in the class body of a component.
the #namedArgs syntax is consistent across class-based components and template-only components as template-only components do not have a this.

Multiple array controllers inside an Object controller Ember

I've a template whose model contains two different sets of array elements. I've to list them with a check box, so that user can select multiple items from both the lists. I've to collect all the items.
I started as follows
<script type="text/x-handlebars" data-template-name="temp">
<p>List 1</p>
<ul>
{{#each list1}}
<li>
{{input type="checkbox"}}
{{name}}
</li>
{{/each}}
</ul>
<p>List 2</p>
<ul>
{{#each list2}}
<li>
{{input type="checkbox"}}
{{name}}
</li>
{{/each}}
</ul>
</script>
I thought to have controllers for the two lists separately. But not sure how to get the list together. The place where I've the total control could be "TempController", but not sure how to get the checked property of each item in the two different lists.
I hope I've explained my functionality. Hope there is a solution or work around for this.
Thanks.

How to get current model for a route from a controller or a view?

I want to implement item-list/item-detail pattern in Ember, but the nuance is that the detail view must appear next to the selected item. E.g:
<ul>
<li><div>Post 1<div></li>
<li><div>Post 2<div></li>
<li><div>Post 3<div></li>
<li>
<div>Post 4<div>
<div>
<ul>
<li>Comment 1</li>
<li>Comment 2</li>
<li>Comment 3</li>
</ul>
</div>
</li>
<li><div>Post 5<div></li>
</ul>
The Handlebars template I tried is:
<script type='text/x-handlebars' data-template-name='posts'>
<ul>
{{#each model}}
{{#linkTo 'post' this}}
<div>{{title}}</div>
{{/linkTo}}
{{#if isSelected}} <!-- How to implement isSelected ? -->
<div>{{!-- render selected post's comments --}}</div>
{{/if}}
{{/each}}
</ul>
</script>
I tried this in controller:
App.PostController = Em.ObjectController.extend({
isSelected: function() {
return this.get('content.id') === /* what to put here? */;
}
});
What I'm stuck with is how to implement isSelected in 'Ember'-way? Am I going in right direction?
You are on the right track. The trick is to use a different controller to wrap products in the item-list vs. the item-detail. So start by specifying that the handlebars {{each}} helper should wrap each entry in a ListedProductController
{{#each model itemController="listedProduct"}}
Now define ListedProductController, adding the isSelected function you'd been writing. Now it can reference the singleton ProductController via the needs array, comparing the product that was set by the router to the listed product.
App.ProductController = Ember.ObjectController.extend({});
App.ListedProductController = Ember.ObjectController.extend({
needs: ['product'],
isSelected: function() {
return this.get('content.id') === this.get('controllers.product.id');
}.property('content.id', 'controllers.product.id')
});
I've posted a working example here: http://jsbin.com/odobat/2/edit

Ember.js nested views get very slow

I have a two-level deep data model that I want to display with Ember.js as nested lists. If I do the simple version it performs quite well:
{{#each parent in content}}
<p>Table {{parent.id}}</p>
<ul>
{{#each item in parent.children}}
<ul>
<li>{{item.position}}</li>
<li>{{item.position}}</li>
<li>{{item.position}}</li>
</ul>
{{/each}}
</ul>
{{/each}}
http://jsfiddle.net/krumpi/TdZJG/
However if instead of displaying the model's properties as raw strings I use nested Ember.Select and Ember.TextArea views the performance suffers a lot, it takes quite a bit after the load button is pressed to display the controls in the page:
{{#each parent in content}}
<ul>
{{#each item in parent.children}}
<ul>
<li>pos: {{item.position}}</li>
<li>
{{view Ember.Select
class="input-small"
contentBinding="App.CheckValues"
selectionBinding="item.status"}}
</li>
<li>{{view Ember.TextArea class="textarea-animated" name="description" valueBinding="item.comment"}}</li>
</ul>
{{/each}}
</ul>
{{/each}}
http://jsfiddle.net/krumpi/wtwHN/
Would you have any suggestion on how to improve performance. This is done with ember-1.0.0-pre4
Instead of using Ember select and textarea views use normal html tags for them and bind only the attributes. Those views usually occupy more memory and writing them inside a nested structure will expectedly make your code run slow.

How to render hasMany associations each with their own controller

So my models are set up like this :
App.Post = DS.Model.extend
comments: DS.hasMany 'App.Comment'
App.Comment = DS.Model.extend
post: DS.belongsTo 'App.Post'
I'm trying to create a view that has all posts and all comments display, but I need to decorate the comment objects.
This is what I'd like to do but, to no avail :
<ul>
{{#each post in controller}}
<li>{{post.title}}</li>
<ol>
{{#each comment in post.comments itemController="comment"}}
<li>{{comment.body}}</li>
{{/each}}
</ol>
{{/each}}
</ul>
Properties defined in a App.CommentController are simply not found by the template.
I suspect that Ember.OrderedSet does not implement the itemController param - is there a workaround for this?
You need to use the new expiremental control tag. This will load the view and controller for the specified type:
<ul>
{{#each post in controller}}
<li>{{post.title}}</li>
<ol>
{{#each comment in post.comments}}
{{ control "comment" comment }}
{{/each}}
</ol>
{{/each}}
</ul>
You will need to enable this expiremental feature first. Put this before ember is loaded:
<script type='application/javascript'>
ENV = {
EXPERIMENTAL_CONTROL_HELPER: true
};
</script>
Also, you will need to specify that the controller for comments should not be a singleton, otherwise there will only be one controller instantiated for all comment views:
// this is needed to use control handlebars template properly per
// https://github.com/emberjs/ember.js/issues/1990
App.register('controller:comment', App.CommentController, {singleton: false });