【问题标题】:How should I be loading a related model into a template with Ember?我应该如何使用 Ember 将相关模型加载到模板中?
【发布时间】:2014-08-24 15:26:45
【问题描述】:

我才刚刚开始使用 Ember,并在几个概念上苦苦挣扎。我在以前的应用程序中使用了 Knockout,这很棒,我已经可以看到 Ember 将如何帮助我变得更有条理并编写更少的代码。虽然我可以回到 Knockout 并很快启动并运行它,但我真的很想坚持使用 Ember。

我正在努力解决的问题是加载相关记录的正确方法和位置。我的应用程序有一个系统列表,以及与每个系统相关的供应商列表。每个系统可能有一个或多个供应商,反之亦然。

到目前为止,我有一个名为 Systems 的路由,带有相应的控制器和模板。路由上的模型挂钩从 API 获取系统列表(我使用的是 Ember Data)。系统通过模板显示为列表,当用户选择一个(通过单选按钮)时,我需要加载并显示相关供应商。这是我不确定的一点。

我没有在此处更改 URL,只是在系统列表下方显示了额外的供应商列表,因此添加新路线听起来不太正确。从概念上讲,最好的方法是什么?

  • 我应该使用控制器中的操作来加载和显示数据吗?这听起来也不对,因为模型钩子都在路由中。
  • 我是否应该预先加载所有数据并使用控制器对其进行过滤(并切换显示)?
  • 有没有正确或更好的方法?

这是当前代码。

系统模型

import DS from 'ember-data';

export default DS.Model.extend({
    name: DS.attr('string'),
    suppliers: DS.hasMany('supplier')
});

供应商模式

import DS from 'ember-data';

export default DS.Model.extend({
    name: DS.attr('string'),
    systems: DS.hasMany('system')
});

系统路线

import Ember from 'ember';

export default Ember.Route.extend({
    model: function() {
        return this.store.find('system');
    }
});

系统控制器

import Ember from 'ember';

export default Ember.ObjectController.extend({
    systemSelected: false,

    actions: {
        selectSystem: function(id) {
            this.set('systemSelected', true);

            console.log(id);
        },
        selectSupplier: function(supplier) {
            console.log(supplier);
        }
    }
});

系统模板

<h1>systems</h1>

<form id="systems">
    <fieldset>
        <div class="form-group">
            <label for="system" class="control-label">Select the system</label>
            {{#each}}
                <div class="radio">
                    <label>
                        <input type="radio" name="system" value="{{id}}" {{action 'selectSystem' id}}>
                        <span>{{name}}</span>
                    </label>
                </div>
            {{/each}}
        </div>

        {{#if systemSelected}}
            <div class="form-group">
                <label for="supplier" class="control-label">Select the supplier</label>
                {{#each suppliers}}
                    <div class="radio">
                        <label>
                            <input type="radio" name="supplier" value="{{id}}" {{action 'selectSupplier' supplier}}>
                            <span>{{name}}</span>
                        </label>
                    </div>
                {{/each}}
            </div>
        {{/if}}
    </fieldset>
</form>

【问题讨论】:

    标签: ember.js ember-data


    【解决方案1】:

    处理这个问题的方法很简单。您只需在路线中加载两个相关模型。您可以使用 RSVP 来做到这一点。

    首先,我们需要一个供应商控制器,但这只是一个非常基本的用于存储所有供应商的控制器:

    App.SuppliersController = Ember.ArrayController.extend();
    

    在您的 Systems Route 中,像这样获取模型并将它们设置为正确的模型属性:

    import Ember from 'ember';
    
    export default Ember.Route.extend({
        model: function() {
            return Ember.RSVP.hash({
               systems: store.find('system'),
               suppliers: store.find('suppliers')
            });
        },
        setupController(controller,models) {
            this.controllerFor('systems').set('model',models.systems);
            this.controllerFor('suppliers').set('model',models.suppliers);
        }
    });
    

    然后在您的系统控制器中,将供应商控制器添加到需求中:

    import Ember from 'ember';
    
    export default Ember.ObjectController.extend({
        needs:['systems'],
        systemSelected: false,
    
        actions: {
            selectSystem: function(id) {
                this.set('systemSelected', true);
    
                console.log(id);
            },
            selectSupplier: function(supplier) {
                console.log(supplier);
            }
        }
    });
    

    您可能希望为 Systems Controller 使用 ArrayController 而不是 ObjectController,因为它存储多个对象。

    然后在您的 Systems Template 中,您可以访问 Systems Controller 作为主控制器的属性,如下所示:

    <h1>systems</h1>
    
    <form id="systems">
        <fieldset>
            <div class="form-group">
                <label for="system" class="control-label">Select the system</label>
                {{#each system in controllers.systems}}
                    <div class="radio">
                        <label>
                            <input type="radio" name="system" value="{{id}}" {{action 'selectSystem' id}}>
                            <span>{{name}}</span>
                        </label>
                    </div>
                {{/each}}
            </div>
    
            {{#if systemSelected}}
                <div class="form-group">
                    <label for="supplier" class="control-label">Select the supplier</label>
                    {{#each suppliers}}
                        <div class="radio">
                            <label>
                                <input type="radio" name="supplier" value="{{id}}" {{action 'selectSupplier' supplier}}>
                                <span>{{name}}</span>
                            </label>
                        </div>
                    {{/each}}
                </div>
            {{/if}}
        </fieldset>
    </form>
    

    你去吧。希望有帮助。还有其他方法可以做到这一点,但这是我所知道的最Emberific的方法。

    【讨论】:

    • 谢谢。这是有道理的,我可以看到这如何有助于创建模块化应用程序。我现在不确定的一点是我应该如何根据用户选择的系统过滤供应商列表。虽然我可以并且目前正在获取路线加载时的完整供应商列表,但根据选择的系统,应该只显示其中的一些。这种过滤应该发生在系统或供应商控制器中吗?它是如何工作的?似乎将两个模型都直接加载到 System 控制器中会更简单,但这似乎不包含 ember 方式。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-01-12
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多