2012-09-26 142 views
10

我正在用EmberJS v1.0.pre编写一个应用程序。我有一个ArrayController其中包含所有人的列表。有一堆嵌套的视图显示了每个宠物的人,他们的宠物和笔记。EmberJS嵌套视图和控制器

|----------------------------------------| 
| 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立场。有顶级的数组控制器,然后是所有单独的视图。如果我想删除一个笔记,或编辑它,似乎我需要将视图的上下文传递给控制器​​。

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

这对我来说真的很不好,视图不应该是数据的权威来源。我的假设是ArrayController会实例化一个itemControlerClass以及itemViewClass

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

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

+0

查看http://emberjs.com/guides/outlets/ –

+0

该指南中没有关于我的问题的真实公司信息。我已经阅读过,我会继续提及它,但还没有发现任何东西。 – noazark

+0

检查出来,然后http://stackoverflow.com/questions/12595496/how-can-i-build-a-recursive-view-in-ember/12602743#comment17008361_12602743 –

回答

12

“从单纯的MVC角度来看感觉应该为每个孩子控制器”

你并不需要为每个项目的控制,而是对对象的每个集合的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}} 

正如你所看到的,在子对象的动作都被委托给它的控制器(宠物 - > 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

这是我见过的最完整的例子,谢谢!我会采取这个答案,并与它一起运行。我仍然需要解决一些问题。从视图传递上下文是我对这个问题的原始投诉,但似乎不可避免。另外,控制器不能简单地设置为所有的Notes,因为它们是Pets(宠物)和Pets(宠物)中的孩子。对我来说,这不像是一个建筑问题。我需要首先设置父上下文。我会用我发现的任何更新来更新我的问题。再次感谢。 – noazark

1

你应该使用网点。 它们是可以用不同的控制器处理的Ember视图中的小占位符。

上面的链接上有一个公正的解释,你已经检查并没有发现任何东西。但在你回到那之前,请先阅读:http://trek.github.com/

如果其中任何一个仍然不能帮助你,让我们知道,我会为你组装一个样品。

+0

我已经阅读了两篇文章,甚至在发布之前。我也在使用网点,但网点不会将内容的责任委托给单独的控制器。感谢您提供一个例子,我很乐意看到一个例子。我也会在jsfiddle中掀起一些东西来更好地解释我的问题。 – noazark

+0

我用[小提琴](http://jsfiddle.net/noazark/HmHK3/)更新了我的问题。感谢您的持续帮助。 – noazark

1

我认为this是你正在寻找的东西,看一看,它是非常简单的,你也可以检查this的例子。基本上,你可以实现你想要的插座,路由器和连接你的所有网点的行动。

+0

我会再试一次。这篇文章https://gist.github.com/3002177也有很大的帮助。我认为我的问题一直在使用ArrayController。当真的它应该只是一个带有插座的控制器?那有意义吗? – noazark

+0

你有没有可能提供一个不同的,更相关的例子?你提供的那个与我的问题没有任何关系。具体来说,我的问题不是路由,而是关于委托控制嵌套资源。奥特莱斯有趣,但即使有所有使用它们的建议,仍然没有有用的例子说明他们如何解决我的问题。 – noazark

0

我是新来的灰烬,并一直在寻找一种方式做同样的事情。在顶层ArrayController,我只是用itemController财产,它的伟大工作:

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

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

我的完整的解决方案是在this js fiddle。不幸的是,我得到的PetController实例的工作方式似乎对我很不利。

+0

自v1.0pre以来的更新已经超级有用,我的运气也好多了。我会更深入地研究你所做的事情,看看它是如何发展的! – noazark