Reputation: 60
I'm new to Ember and am using Ember.js 2.10. I'm trying to only use components instead of controllers. I'm trying to create a component that creates a list that is a list of links or just items and is sorted or not sorted based on the properties sent in. I have the link part working, but I can't seem to get the sort working without repeating a lot of code which makes me think I'm doing something wrong. I tried moving the sort logic into a computed property, but it doesn't work. If I don't specify a sortBy
property, it still sorts the list. If I do specify as sortBy
property, I don't get a list at all and the console.log shows what is returned as ComputedProperty.
This seems basic enough that I shouldn't have to do this, so if there is an Ember way of doing this, I'd like to know. Regardless, I'd like to understand what I'm doing wrong for the academic value of it.
app/components/column-list.js
import Ember from 'ember';
export default Ember.Component.extend({
tagName: 'ul',
classNames: ['column-list'],
sortedItems: Ember.computed('items', 'sortBy', function() {
if (this.get('sortBy') !== undefined) {
let sd = [ this.get('sortBy') ];
return Ember.computed.sort(this.get('items'), sd);
} else {
return this.get('items');
}
}),
});
app/templates/components/column-list.hbs
{{#if sortBy}}
{{#each sortedItems as |item|}}
<li>
{{#if link}}
{{#link-to link item.id}}
{{yield item}}
{{/link-to}}
{{else}}
{{yield item}}
{{/if}}
</li>
{{/each}}
{{else}}
{{#each items as |item|}}
<li>
{{#if link}}
{{#link-to link item.id}}
{{yield item}}
{{/link-to}}
{{else}}
{{yield item}}
{{/if}}
</li>
{{/each}}
{{/if}}
app/templates/category/index.hbs
{{#column-list class="categories" sortBy="title" link="category.show" items=model as |i|}}
{{i.title}}
{{/column-list}}
mirage/fixtures/category.js
export default [
{
id: 'main-dishes',
title: 'Main Dishes',
}, {
id: 'cakes-pies-and-sweets',
title: 'Cakes, Pies & Sweets',
}, {
id: 'langappie',
title: 'Langappie',
}, {
id: 'dips-and-sauces',
title: 'Dips & Sauces',
}, {
id: 'meat-dishes',
title: 'Meat Dishes',
}, {
id: 'vegetable',
title: 'Vegetable',
}, {
id: 'seafood-dishes',
title: 'Seafood Dishes',
}, {
id: 'bread-and-cereals',
title: 'Bread & Cereals',
}
];
Update:
I twiddled the twiddle that @Jovica made and I'm getting "Assertion Failed: The sort definition for 'sortedItems' on must be a function or an array of strings", so I think I still have something wrong. Link to twiddle
Update2:
I found that I had a typo in my twiddle and got it working properly. The new twiddle has the right fix. Now to figure out why ember-mirage is ordering the data without me asking, but that is a different problem.
Upvotes: 0
Views: 527
Reputation: 6577
Returning the Ember.computed.sort
macro isn't doing what you think it is. You would have to use the sort methods on the Array class. The dependent keys are also not properly declared, it would be items.[]
if the list is to be updated.
Here's a suggested solution that updates the sorting whenever the sort key that's passed into the component changes:
export default Ember.Component.extend({
appName: 'Ember Twiddle',
dishes: foo,
sortedItems: Ember.computed.sort('dishes', 'sortBy')
didReceiveAttrs() {
if (this.get('sortBy')) {
this.set('sortBy', [ this.get('sortBy') ]);
else {
this.set('sortBy', []);
}
}
});
And here's the template you need, because when sortBy
is an empty array, the computed macro will not sort the array:
{{#each sortedItems as |item|}}
<li>
{{#if link}}
{{#link-to link item.id}}
{{yield item}}
{{/link-to}}
{{else}}
{{yield item}}
{{/if}}
</li>
{{/each}}
Upvotes: 1
Reputation: 622
Try this
sortedItems: Ember.computed('items', 'sortBy', function() {
if (this.get('sortBy') !== undefined) {
let sd = this.get('sortBy');
return this.get('items').sortBy(sd);
} else {
return this.get('items');
}
}),
or shorter version
sortedItems: Ember.computed('items', 'sortBy', function() {
let sortTerm = this.get('sortBy'),
items = this.get('items');
return Ember.isBlank(sortTerm) ? items : items.sortBy(sortTerm);
}
Upvotes: 0