【问题标题】:EmberJS Nested Views and ControllersEmberJS 嵌套视图和控制器
【发布时间】:2012-09-18 02:53:16
【问题描述】:

我正在使用 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 中实现这一点。有顶部的 Array 控制器,然后是所有单独的视图。如果我想删除或编辑笔记,似乎我需要将视图的上下文传递给控制器​​。

// in the view
click: function () {
  this.get('controller').updateNote(this.get('content'))
}

这让我感觉很糟糕,视图不应该是数据的权威来源。我的假设是 ArrayController 将实例化 itemControlerClass 以及 itemViewClass

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

更新:对不起,我不小心删除了小提琴!我正在为最终解决方案做一些工作,所以我将尝试使用该解决方案创建一个新的小提琴。

【问题讨论】:

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


【解决方案1】:

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

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

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

我的完整解决方案在this js fiddle。不幸的是,我让PetController 实例工作的方式对我来说似乎很老套。

【讨论】:

  • 自 v1.0pre 以来的更新非常有帮助,而且我的运气要好得多。我会进一步深入研究你所做的事情,看看进展如何!
【解决方案2】:

“从纯 MVC 的角度来看,每个孩子都应该有一个控制器”

您不需要为每个项目设置一个控制器,而是为每个对象集合(人物、宠物、便笺)设置一个 ArrayController。顺便说一句,对子对象(狗、笔记)的任何操作都不应该传递给App.PersonsController。这将违反Separation of Concerns 原则。

Ember.Router 文档涵盖了您希望将视图嵌套在单个对象中的情况(例如 /:people_id)。但是您想为一组对象嵌套视图。我想不出嵌套{{outlet}} 视图的方法,但您可以执行以下操作:

在 3 个 ArrayController 中加载对象 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 -> 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});
   }
});  

【讨论】:

  • 这是我见过的最完整的问题示例,谢谢!我将接受这个答案并运行它。不过,我仍然需要解决一些问题。从视图中传递上下文是我对这个问题的最初抱怨,但这似乎是不可避免的。此外,控制器不能简单地设置为所有注释,因为它们是(字面上嵌入)宠物的孩子,并且与宠物和人相同。对我来说,这感觉不像是架构问题。我想我需要先设置父上下文。我会用我发现的更多内容更新我的问题。再次感谢。
【解决方案3】:

我认为this 是您正在寻找的,看一看,它非常简单,您也可以查看this 示例。基本上,您可以通过网点、路由器和连接所有网点的操作来实现您想要的。

【讨论】:

  • 我会再试一次。这篇 gist.github.com/3002177 的文章也提供了很大的帮助。我认为我的问题一直在使用 ArrayController。什么时候它应该只是一个带插座的控制器?这有意义吗?
  • 您能否提供一个不同的、更相关的示例?您提供的与我的问题没有任何相似之处。具体来说,我的问题不在于路由,而在于将控制权委托给嵌套资源。插座很有趣,但即使有所有使用它们的建议,仍然没有有用的例子说明它们如何解决我的问题。
【解决方案4】:

您应该使用插座。 它们是 Ember 视图中的小“占位符”,可以使用不同的控制器进行处理。

上面的链接对它们有一个公平的解释,您已经检查过但什么也没找到。但在你回过头来之前,请先阅读以下内容:http://trek.github.com/

如果其中任何一个仍然无法帮助您,请告诉我,我会为您整理一个示例。

【讨论】:

  • 我已经阅读了这两篇文章,甚至在我发帖之前。我也在使用网点,但是网点不会将内容的责任委托给单独的控制器。谢谢你提供一个例子,我很想看看。我还将在 jsfiddle 中编写一些内容以更好地解释我的问题。
  • 我已经用fiddle 更新了我的问题。感谢您一直以来的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-05-02
  • 1970-01-01
  • 2013-02-23
相关资源
最近更新 更多