0

几周以来,我一直在尝试学习 Ember 的基础知识,目前在通过控制器中的操作更改模型中的数据时遇到了问题。

我发现的所有示例似乎都使用一维夹具。我正在使用的灯具如下所示:

App.ClassGroup = DS.Model.extend({
    className: DS.attr('string'),
    isActive: DS.attr('number'),
    students: DS.hasMany('Students',{async:true}),
    selected: DS.hasMany('Students',{async:true})
});

App.ClassGroup.FIXTURES = [
    {
        id: 123,
        className: 'Class 1',
        isActive: 1,
        students: [11, 22, 33, 44, 55],
        selected: [11, 22, 33, 44, 55]
    },
    {
        id: 456,
        className: 'Class 2',
        isActive: 0,
        students: [66, 77, 88, 99],
        selected: [66, 88, 99]
    },
    {
        id: 789,
        className: 'Group 1',
        isActive: 0,
        students: [77, 22],
        selected: []
    }
];

App.Students = DS.Model.extend({
    first: DS.attr('string'),
    last: DS.attr('string'),
    classes: DS.hasMany('ClassGroup')
});

App.Students.FIXTURES = [
    {
        id: 11,
        first: 'Student',
        last: 'One',
        classes: [123]
    },
    {
        id: 22,
        first: 'Student',
        last: 'Two',
        classes: [123, 789]
    },
    {
        id: 33,
        first: 'Student',
        last: 'Three',
        classes: [123]
    },
    {
        id: 44,
        first: 'Student',
        last: 'Four',
        classes: [123]
    },
    {
        id: 55,
        first: 'Student',
        last: 'Five',
        classes: [123]
    },
    {
        id: 66,
        first: 'Student',
        last: 'Six',
        classes: [456]
    },
    {
        id: 77,
        first: 'Student',
        last: 'Seven',
        classes: [456, 789]
    },
    {
        id: 88,
        first: 'Student',
        last: 'Eight',
        classes: [456]
    },
    {
        id: 99,
        first: 'Student',
        last: 'Nine',
        classes: [456]
    }
];

我的控制器如下所示:

var IndexController = Ember.ArrayController.extend({
    actions: {
        isActiveTog: function(id){
            console.log(this);
            console.log(this.store.get('model'));

            var getter = this.get('classgroup');
            console.log(getter);
        }
    },
    classCount: function(){
        return this.get('length');
    }.property('@each')
});

export default IndexController;

这是我们的路由器:

import Students from "appkit/models/students";
import ClassGroup from "appkit/models/classgroup";

export default Ember.Route.extend({
    model: function() {
        return this.store.find('classgroup');
    },
    setupController: function(controller, model){
        this._super(controller, model);

        controller.set('students', this.store.find('students'));
        controller.set('classgroup', this.store.find('classgroup'));
    }
});

这是each我们的车把模板中的块(我删除了其余部分,因为它太笨重了):

{{#each classgroup}}
            <li id="c_{{unbound this.id}}" class="classMenu manageMenuWidth">
                <span class="classSA" id="c_{{unbound this.id}}_sas"><input type="checkbox" name="c_{{unbound this.id}}_chk" id="c_{{unbound this.id}}_chk" /></span>
                <span id="c_{{unbound this.id}}_nam" {{bind-attr class=":classLayout isActive:activeSelection"}} {{action "isActiveTog" this.id on="click"}}>{{unbound this.className}}</span>
                {{#view 'toggleclass'}}<span class="togControl" id="c_{{unbound this.id}}_tog"></span>{{/view}}
            </li>
            <ul id="c_{{unbound this.id}}_sts" class="students manageMenuWidth">
                {{#each students}}
                    <li class="student" id="s_{{unbound this.id}}_c_{{unbound classgroup.id}}">
                        <span class="studentChk" id="s_{{unbound students.id}}_c_{{unbound classgroup.id}}_img">{{unbound this.last}}, {{unbound this.first}}</span>
                        <input type="checkbox" name="s_{{unbound students.id}}_c_{{unbound classgroup.id}}_chk" id="s_{{unbound students.id}}_c_{{unbound classgroup.id}}_chk" />
                    </li>
                {{/each}}

我尽可能多地包含了我们的代码,因为我对 Ember 还很陌生,我想确保你拥有帮助回答这个问题所需的所有信息,即使这意味着给你太多。

为了让您不会挖掘太多,这里有一些更多信息。在车把模板中有一行{{action "isActiveTog" this.id on="click"}}在我们的范围内。

这将在我们的控制器中调用一个函数,isActiveTog我们想用它来切换isActive模型中的值,以在each循环中单击任何“类组”记录。

例如,用户单击“Class 1”,它有一个动作调用isActiveTog,传入 ID = 123。我希望我在控制器中的动作将 ClassGroup[123][isActive] 的值从 0 切换到 1,反之亦然反之亦然。

我可以说我的控制器被正确调用,因为我可以放入{{classCount}}我的模板并在输出中看到“3”。因此,问题是我无法找到一种方法来切换控制器中的值。

如何使用this.store.find()搜索classgroupID 等于传递给操作的任何内容的行,然后访问该类记录的 isActive 值。然后我需要使用this.store.set()写回模型。

4

2 回答 2

2

似乎您来自 jQuery 背景,因为您如何尝试id通过模板将 ClassGroup 记录嵌入到 DOM 中(这当然没有错,因为这就是我第一次开始使用 Ember 时所做的事情来自 jQuery 沉重的背景)。如果您注意到自己这样做了,那么您可能正在以非 ember 的方式做某事。通常,如果您需要集成一些第三方 jQuery 库,您应该只通过 ID 访问 DOM 元素。

好的,现在您知道要注意什么了,我们应该如何以 Ember 方式完成您想要的工作?

可能有几种方法可以解决它,但对我来说效果很好的是为每个单独的 ClassGroup 创建另一个控制器,该控制器扩展 ObjectController 而不是 ArrayController。所以你会有

ClassGroupsController (ArrayController) -> ClassGroupController (ObjectController)

请注意,数组控制器是复数形式的。这允许您管理每个单独的 ClassGroup 记录的状态,因为每个 ClassGroup 记录现在都有自己的控制器和自己的视图。

所以首先创建一个数组控制器来管理 ClassGroups 的集合:

App.ClassGroupsController = Ember.ArrayController.extend({

});

ClassGroupController (Object) 应该有一个监听点击事件的视图。当我们得到一个点击事件时,我们会在控制器(ClassGroupController)上触发一个名为selected.

App.ClassGroupView = Ember.View.extend({
    templateName: 'classGroup',
    /*
    By specifying the tagName for this view we are telling ember
    we want to wrap the view in a <tr> element.  This is because
    each classGroup is going to be a row in our table.  By default
    each view is wrapped in a <div>
    */    
    tagName: 'tr',
    /*
    This is the click handler that is called whenever the user
    clicks on this view (in this case one of our <tr> elements
    that is displaying our ClassGroup Model for us.  The event
    parameter is the jQuery event object.
    */
    click: function(event){
        /*
        We want to forward this event to the controller where
        we can do some logic based on the fact that it was clicked.        
        */
        this.get('controller').send('selected');   
    }
});

现在我们为 ClassGroup 创建我们的 ObjectController,它正在等待并侦听用户单击该个人时selected发送的操作。ClassGroupViewClassGroup

App.ClassGroupController = Ember.ObjectController.extend({    
    actions:{
        /*
        This is the action we received from our view which was
        based on the user clicking on one of the <li> elements
        representing a ClassGroup Model
        */
        selected: function(){            
            console.info("You selected: " + this.get('className'));    
            /*
            Now we can easily toggle the isActive state of our model
            */
            this.toggleProperty('isActive');
            console.info("My isActive state is now: " + this.get('isActive'));
        }
    }
});

现在我们需要在我们的模板中将其连接起来。

{{#each itemController="classGroup"}}
    {{view App.ClassGroupView}}  
{{/each}}

请注意我如何指定要使用 classGroup 作为我的 ArrayController 的 itemController。这里我直接在模板中指定。您还可以使用itemController属性在 ArrayController 本身中指定它。例如:

App.ClassGroupsController = Ember.ArrayController.extend({
    itemController: 'classGroup'   
});

这是一个有效的 JSFIddle,使用您的固定装置来演示整个概念:

http://jsfiddle.net/NQKvy/872/

于 2014-03-28T23:33:41.037 回答
1

直接回答你的问题

您可以通过 id 找到记录并使用

this.store.find('classgroup', id).then(function (classgroup) {
    classgroup.toggleProperty('isActive');
});

但是,在您的情况下,您实际上并不需要,因为您可以通过记录

所以在你看来使用

{{action "isActiveTog" this on="click"}}

而不是this.id然后直接在控制器中修改它

isActiveTog: function(classgroup){
    classgroup.toggleProperty('isActive');
    // classgroup.save();
}
于 2014-03-29T07:13:44.810 回答