Pergunta

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

Foi útil?

Solução

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})
    ]);
});
​

Outras dicas

I would structure your application like this:

  1. A model with just a list o part objects. Each object holds how many of that part exist in each country.
  2. A controller that filters that list depending on countries selected.
  3. A view that sets in the controller which countries are selected.
  4. A view that displays a list from the controller with the selected parts.

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.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top