EmberJS嵌套视图和控制器

时间:2012-09-26 13:05:51

标签: javascript model-view-controller ember.js

我正在用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会将itemControlerClassitemViewClass一起实例化。

更新:我创建了一个fiddle来更好地说明我的问题。该功能有意不完整,目的是通过在单击列表中的项目时增加内容来完成功能。

更新:抱歉,我在事故中删除了小提琴!我正在为最终解决方案做一些工作,所以我会尝试用解决方案创建一个新的小提琴。

4 个答案:

答案 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)

我认为this正是您所寻找的,看看,它非常简单,您也可以查看this示例。基本上,您可以使用插座,路由器和连接所有插座的操作来实现您的目的。

答案 3 :(得分:0)

我是Ember的新手,一直在寻找一种方法来做类似的事情。在顶层的ArrayController中,我只使用了itemController属性并且效果很好:

App.PeopleController = Ember.ArrayController.extend({
    itemController: "Person"
});

App.PersonController = Ember.ObjectController.extend //...

我的完整解决方案位于this js fiddle。不幸的是,我让PetController个实例工作的方式对我来说似乎很苛刻。