【问题标题】:ember.js how to display different filtered lists for a view? complex setupember.js 如何为视图显示不同的过滤列表?复杂的设置
【发布时间】:2012-03-01 18:11:48
【问题描述】:

我有一个应用程序,其中我有一个汽车视图,我有一个国家列表,每个国家都有一个复选框,当我检查一个国家时,它会在下面显示一个视图,其中包含该国家可用的零件列表。

检查更多国家/地区会在页面下方显示更多国家/地区的零件。

零件都存储在一个地方,但需要按国家字段过滤,以仅显示该国家/地区该部分中的零件。

我可以创建国家/地区列表,选中后会在下面显示一个国家/地区部分,其中包含零件列表,但我如何过滤以仅显示该国家/地区。我是否需要为每个国家/地区创建视图并为每个国家/地区创建一个控制器以显示?

肯定有更好的办法。

编辑:

这就是我需要显示页面的方式:

Coutries : UK <- selected

           USA

           China <- selected


Parts available in UK:

....

Parts available in China

....

所以我需要显示每个所选国家/地区的单独列表。

请帮忙 瑞克

【问题讨论】:

    标签: javascript ember.js


    【解决方案1】:

    这可能最好使用嵌套视图来解决。你可以看到my jsFiddle here

    我不认为这是一个非常复杂的方法,但是如果您对设计有任何疑问,请告诉我。

    车把:

    <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>
    ​
    

    应用代码:

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

    【讨论】:

    • 嗨,罗伊,感谢您的出色回答。只有一个问题:如果我进入控制台并尝试添加像这样的另一部分App.get('partsController').pushObjects([ App.Part.create({id: 999, name: "part999", countryId: 2})]); 我如何让它添加到相关部分而无需再次单击复选框?再次感谢
    • 抱歉,我忘记在我的 filtersParts 计算属性的定义中添加一个要注意的属性。我已经更新到代码和 jsFiddle。这是否成功回答了您的问题?
    • 哇,太快了,非常感谢,是的,这完全回答了我的问题。
    【解决方案2】:

    我会像这样构建您的应用程序:

    1. 仅包含部分对象列表的模型。每个对象包含每个国家/地区存在的该部分的数量。
    2. 根据所选国家/地区过滤列表的控制器。
    3. 在控制器中设置所选国家/地区的视图。
    4. 一个视图,显示来自控制器的列表以及所选部件。

    我在这里做了:

    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();
    
    })
    

    还有车把:

    <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>
    

    【讨论】:

    • 嗨,马丁非常感谢您的广泛回答。这将解决我的问题,但我认为这是 Roy 提供的更清洁的解决方案。我希望你同意。谢谢
    【解决方案3】:

    对于部件列表,您可以使用绑定到控制器上的集合的#each 助手。控制器可以观察到绑定到当前选定国家的控制器。 When the selection changes, it would update the collection, which would automatically update your parts list.

    【讨论】:

    • 谢谢,但这将创建一个列表,其中包括所选国家/地区的所有可用部件。但我需要单独显示这些。请参阅我上面的编辑。有什么想法吗?
    猜你喜欢
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多