-
Notifications
You must be signed in to change notification settings - Fork 7
10.0.0 belongsTo Association
- Define and render a belongsTo association
- Use query-params to filter a list
- Update the belongsTo association
See the installation instructions. Use tag 10.0.0.
Open frontend/app/templates/products.hbs
and update the code as follows to show the category's name:
...
<p class='badge'>{{product.categoryName}}</p>
<p>{{product.description}}</p>
...
- Make the same changes to
frontend/app/templates/products/show.hbs
:
...
<p class='badge'>{{model.categoryName}}</p>
<p>{{model.description}}</p>
...
- Open
frontend/app/models/product.js
and add acategory
association and a method for its name:
export default DS.Model.extend({
...
reviews: DS.hasMany('review'),
category: DS.belongsTo('category', { async: false }),
categoryName: Ember.computed('category', function() {
return this.get('category.name');
})
});
- Inspect the error shown in the Console tab in the browser. Ember doesn't know the
category
model yet. Let's define it. - In the
frontend
folder, enter the commandember g model category
. - Open
frontend/app/models/category.js
and add the following attributes:
export default DS.Model.extend({
name: DS.attr()
})
Open frontend/app/templates/products.hbs
and replace the <a>
tags within <div class='content-navigation'>
with:
{{#each uniqCategories as |category|}}
{{#link-to 'products' class='list-group-item'}}{{category.name}}{{/link-to}}
{{/each}}
- Open
frontend/app/controllers/products.js
and add the following properties:
export default Ember.Controller.extend({
...
categories: Ember.computed.mapBy('model', 'category'),
uniqCategories: Ember.computed.uniq('categories')
});
Open frontend/app/templates/products.hbs
and add a query-param to the {{link-to}}
helper:
{{#link-to 'products' (query-params category=category.name) class='list-group-item'}}
- Open
frontend/app/controllers/products.js
, add thequeryParams
property and update thefilteredContent
function so that it uses thecategory
value for displaying the proper products:
export default Ember.Controller.extend({
...
queryParams: ['category'],
category: '',
...
filteredContent: Ember.computed(..., 'category', function() {
var products = this.model,
search = new RegExp(this.get('search'), 'i'),
category = this.get('category');
products = products.filter(function(product) {
var str = product.get('title') + product.get('description');
return search.test(str);
});
if (category) {
products = products.filterBy('category.name', category);
}
return products;
}),
...
});
- Open
frontend/app/templates/application.hbs
and update the{{link-to}}
helper to reset the filter:
{{#link-to 'products' (query-params category='')}}Products{{/link-to}}
- Open
frontend/app/templates/products.hbs
and add markup to show the number of products per category. Change:
{{#link-to 'products' (query-params category=category.name) class='list-group-item'}}{{category.name}}{{/link-to}}
to
{{#link-to 'products' (query-params category=category.name) class='list-group-item'}}{{category.name}}<small> ({{category.products.length}})</small>{{/link-to}}
- Open
frontend/app/models/category.js
and add the following property:
export default DS.Model.extend({
...
products: DS.hasMany('product')
});
- In the terminal, from the
frontend
folder enterember install emberx-select
- Open
frontend/app/templates/products/show.hbs
and, within the form between the price and image add the following code:
<div class='form-group'>
{{#x-select value=model.category.id action='selectCategory' class='form-control'}}
{{#each categories as |category|}}
{{#x-option value=category.id}}
{{category.name}}
{{/x-option}}
{{/each}}
{{/x-select}}
</div>
The ProductsShowController does not have a property categories
yet, so let's add it. We also will add the setCategory
action for updating the product.
- Open
frontend/app/controllers/products/show.js
and add the following properties:
export default Ember.Controller.extend({
categories: Ember.computed(function() {
return this.store.peekAll('category');
}),
actions: {
...
selectCategory(value) {
this.model.set('category', this.store.peekRecord('category', value));
}
}
});
As you might notice, currently when you edit a product, the
Update
button will not get enabled when you select another category. This is because the model does not get marked as dirty when an association changed. I think this is a bug that definitely has some workarounds, but are not applied here.