I have a an app where i have a car view and i have a list of countries with a checkbox against each that when i check a country it displays a view below with a list of parts available in that country.
Checking more countries displays the parts in more countries down the page.
The parts are all stored in one place but need to be filtered by coutry field to just display parts in that section for that country.
I can create the list of countries and when checked it displays a country section below with the parts list in it but how do i filter to only display for that country. Do i need to create views for each country and a controller for each countries parts to display ??
Surely there is a better way.
EDIT :
This is how i need the page to be displayed :
Coutries : UK <- selected
USA
China <- selected
Parts available in UK:
....
Parts available in China
....
So i need seperate lists displayed ofr each country selected.
Please help Rick
This would probably be best solved using nested views. You can see my jsFiddle here.
I don't think it's a terribly complicated approach, but if you have any questions about the design please let me know.
Handlebars:
<script type="text/x-handlebars">
{{#each App.countriesController}}
{{view Ember.Checkbox titleBinding="name" valueBinding="isChecked"}}
{{/each}}
<hr />
{{#each App.countriesController}}
{{#if isChecked}}
{{view App.PartsByCountryView contentBinding="this" partsListBinding="App.partsController"}} <br />
{{/if}}
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="selected-country">
Country: {{content.name}} <br />
Parts:
{{#each filteredParts}}
{{name}}
{{/each}}
</script>
App Code:
window.App = App = Ember.Application.create();
/**************************
* Models
**************************/
App.Country = Ember.Object.extend({
id: null,
name: "",
isChecked: null
});
App.Part = Ember.Object.extend({
id: null,
name: "",
countryId: null
});
/**************************
* Views
**************************/
App.PartsByCountryView = Ember.View.extend({
content: null,
partsList: null,
templateName: 'selected-country',
filteredParts: function() {
return this.get("partsList").filterProperty('countryId', this.getPath('content.id'))
}.property('partsList.@each').cacheable()
});
/**************************
* Controllers
**************************/
App.set('countriesController', Ember.ArrayController.create({
content: Ember.A()
}));
App.set('partsController', Ember.ArrayController.create({
content: Ember.A()
}));
/**************************
* App Logic
**************************/
$(function() {
App.get('countriesController').pushObjects([
App.Country.create({id: 1, name: "USA"}),
App.Country.create({id: 2, name: "UK"}),
App.Country.create({id: 3, name: "FR"})
]);
App.get('partsController').pushObjects([
App.Part.create({id: 1, name: "part1", countryId: 1}),
App.Part.create({id: 2, name: "part2", countryId: 1}),
App.Part.create({id: 3, name: "part3", countryId: 1}),
App.Part.create({id: 4, name: "part4", countryId: 2}),
App.Part.create({id: 5, name: "part5", countryId: 2}),
App.Part.create({id: 6, name: "part6", countryId: 2}),
App.Part.create({id: 7, name: "part7", countryId: 2}),
App.Part.create({id: 8, name: "part8", countryId: 3}),
App.Part.create({id: 9, name: "part9", countryId: 3}),
App.Part.create({id: 10, name: "part10", countryId: 3}),
App.Part.create({id: 11, name: "part11", countryId: 3})
]);
});
I would structure your application like this:
I've done that here:
http://jsfiddle.net/NPeeQ/2/
window.App = Ember.Application.create();
App.model = Ember.Object.create({
parts: Ember.ArrayProxy.create({
content: [
{
name: 'wheel',
stock: {
uk: 3,
fi: 2,
se: 0
}
},
{
name: 'windscreen',
stock: {
uk: 0,
fi: 1,
se: 3
}
}
]}),
countries: ['uk', 'fi', 'se']
});
App.partController = Ember.Object.create({
filterBy: {},
setFilterBy: function (country, on) {
var filterBy = $.extend({}, this.get('filterBy'));
if (on) {
filterBy[country] = true;
} else {
delete filterBy[country];
}
this.set('filterBy', filterBy);
},
// returns all available parts filtered by filterBy.
availableParts: function () {
var parts = App.model.parts;
var filter = this.filterBy;
var arr = [];
App.model.countries.forEach(function(c) {
if (!filter[c]) return;
arr.push({heading:c});
var tmp = App.model.parts.filter(function(p) {
return p.stock[c] && p.stock[c] > 0;
});
arr = arr.concat(tmp);
});
return arr;
}.property('filterBy', 'App.model.parts').cacheable()
});
App.SelectorView = Ember.View.extend({
templateName: 'selector',
click: function(event) {
if (event.target.tagName !== 'INPUT')
return;
var clicked = $(event.target).closest('label');
var index = this.$().find('label').index(clicked);
var country = App.model.countries[index];
var on = event.target.checked;
App.partController.setFilterBy(country, on);
}
});
App.PartsView = Ember.View.extend({
templateName: 'parts'
});
$(function() {
App.selectorView = App.SelectorView.create();
App.partsView = App.PartsView.create();
App.selectorView.append();
App.partsView.append();
})
And the handlebars:
<script type="text/x-handlebars" data-template-name="selector">
{{#each App.model.countries}}
<label><input type="checkbox"/> {{this}}</label>
{{/each}}
</script>
<script type="text/x-handlebars" data-template-name="parts">
{{#each App.partController.availableParts}}
{{#if heading}}
<h2>{{heading}}</h2>
{{else}}
{{name}} <br/>
{{/if}}
{{/each}}
</script>
For the parts list, you could use an #each
helper bound to a collection on a controller. The controller could observe a controller bound to the currently selected countries. When the selection changes, it would update the collection, which would automatically update your parts list.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With