我正在用EmberJS v1.0.pre编写应用程序。我有一个ArrayController
,其中包含所有人的列表。有一堆嵌套的视图显示了每个宠物的人,他们的宠物和笔记。
|----------------------------------------|
| John | <- Person
|----------------------------------------|
| Quincy (Dog) | <- Pet
| - Super ornery | <- Note
| - Likes XYZ Dog food |
| - Will eat your socks |
| |
| Tom (Cat) |
| - Always (not) catching mice |
| |
|----------------------------------------|
| Roger |
|----------------------------------------|
| V (Dog) |
| - Likes XYZ Dog food |
| - Sneezes, but it's ok |
| |
|----------------------------------------|
| ... |
从纯粹的MVC角度来看,每个孩子都应该有一个控制器,但我无法弄清楚如何在Ember中实现这一点。有顶部阵列控制器,然后是所有单独的视图。如果我想删除一个注释或编辑它,似乎我需要将视图的上下文传递给控制器。
// in the view
click: function () {
this.get('controller').updateNote(this.get('content'))
}
这对我来说真的很糟糕,View不应该是数据的权威来源。我的假设是ArrayController会将itemControlerClass
和itemViewClass
一起实例化。
更新:我创建了一个fiddle来更好地说明我的问题。该功能有意不完整,目的是通过在单击列表中的项目时增加内容来完成功能。
更新:抱歉,我在事故中删除了小提琴!我正在为最终解决方案做一些工作,所以我会尝试用解决方案创建一个新的小提琴。
答案 0 :(得分:12)
“从纯粹的MVC角度来看,每个孩子都应该有一个控制器”
每个项目都不需要控制器,而是每个对象集合(People,Pets,Notes)都需要一个ArrayController。顺便说一下,任何关于子对象(狗,笔记)的动作都不应传递给App.PersonsController
。这会违反Separation of Concerns原则。
Ember.Router文档涵盖了您希望在单个对象中嵌套视图的情况(例如/:people_id
)。但是您希望为一组对象嵌套视图。我想不出一种嵌套{{outlet}}
视图的方法,但您可以执行以下操作:
在3个ArrayControllers中加载对象People,Pets,Notes,并将子对象上的操作委托给相应的ArrayController。
App.Router = Ember.Router.extend({
root: Ember.Route.extend({
route: '/',
persons: Ember.Route.extend({
connectOutlets: function(router) {
router.get('applicationController').connectOutlet('persons');
// App.Note.find() fetches all Notes,
// If you are not using ember-data, make sure the notes are loaded into notesController
router.set('notesController.content', App.Note.find());
router.set('petsController.content', App.Pet.find());
}
})
})
});
然后您的people
模板应如下所示:
{{#each person in people}}
<h1>My name is {{person.name}}</h1>
{{#each pet in person.pets}}
I have a pet with name {{pet.name}}
<a {{action delete pet target="App.router.petsController">Delete pet</a>
{{/each}}
{{view Ember.TextField valueBinding="myNewPetName" type="text"}}
<a {{action create myNewPetName person target="controller"}}>
Add a new pet for this person
</a>
{{#each note in person.notes}}
<!-- delete, create, edit ... -->
{{/each}}
如您所见,对子对象的操作被委托给其控制器(pet - &gt; petsController),将对象作为上下文传递。在create
操作的情况下,控制器需要知道宠物belongsTo
是哪个人。因此,我们通过2个上下文:人和宠物的属性(为简单起见,我假设只是宠物的名字)。
在您的App.petsControllers中,您应该采取以下行动:
App.PetsController = Ember.ArrayController.extend({
delete: function(e) {
var context = e.context;
this.get('content').removeObject(context);
// Also, if you use ember-data,
// App.Pet.deleteRecord(context);
},
create: function(e) {
var petName = e.contexts[0]
var person = e.contexts[1];
this.get('content').pushObject({name: petName, person: person});
// with ember-data:
// App.Pet.createRecord({name: petName, person: person});
}
});
答案 1 :(得分:1)
你应该使用网点。 它们是Ember视图中的小占位符,可以使用不同的控制器进行处理。
上面的链接上有一个公平的解释,你已经检查过但没有找到任何内容。但在回到原点之前,请先阅读:http://trek.github.com/
如果其中任何一项对你没有帮助,请告诉我们,我会为你准备一份样本。
答案 2 :(得分:1)
答案 3 :(得分:0)
我是Ember的新手,一直在寻找一种方法来做类似的事情。在顶层的ArrayController中,我只使用了itemController
属性并且效果很好:
App.PeopleController = Ember.ArrayController.extend({
itemController: "Person"
});
App.PersonController = Ember.ObjectController.extend //...
我的完整解决方案位于this js fiddle。不幸的是,我让PetController
个实例工作的方式对我来说似乎很苛刻。