如何在把手模板中获取模型控制器的实例?

时间:2013-09-12 14:11:06

标签: javascript ember.js handlebars.js ember-data

我遇到了一个棘手的问题:我需要在手柄模板中使用新的控制器实例。

以下是我的情况的简要示例。 (请原谅我使用coffeecript)

在恩伯,我有一个模特:

App.Foo = DS.Model.extend

  attr: DS.attr()
  ...

我从端点等加载..然后放入数组控制器:

App.FooArray = Ember.ArrayController.extend

  ###*
   * Array of App.Foo
   * @type {Array}
   */
  content:

  method: ->
    ...

最后,我为这个模型设置了一个'实例'控制器,它实现了更多的方法(即,这不是路由器级别的单独控制器,而是增加模型的装饰器(或代理)方法和事件处理程序):

App.FooController = Ember.ObjectController.extend

  ###*
   * Content
   * @type {App.Foo}
   */
  content: null

  action: ->
    ...

在手柄中,我想迭代App.FooArray中的项目:

{{#each myFooArray}}
  Hi! My attr is {{attr}}
{{/each}}

等。这对参数等非常有效。

然而,当我想使用动作(或属于FooController的其他属性)时,麻烦就开始了

{{#each myFooArray}}
   Hi! My attr is {{attr}} <a {{action 'action'}}>Action me!</a>
{{/each}}

突然间,我的行为无效。那是因为动作助手不会将动作应用于'this',而是应用于更高的控制器,甚至可能在路线级别!

所以要解决这个问题,我需要传递目标(即控制器):

{{action 'action' target=**********}}

嗯,我想要的控制器是App.FooController的实例。 到目前为止,我一直在模型中实例化控制器(哎呀!):

App.Foo = DS.Model.extend

  attr: DS.attr()
  ...
  attrn: DS.attr()

  myController: Ember.computed (->
    App.FooController.create
      content: this
  )

因此迭代如下:

{{#each myFooArray}}
  Hi! My attr is {{attr}} <a {{action 'action' target=myController}}>Action me!</a>
{{/each}}

我知道这很糟糕,但我想不出更好的方法。有人,请帮我看看光!

2 个答案:

答案 0 :(得分:0)

您可以在itemController循环中明确设置each

{{#each myFooArray itemController="foo"}}
  Hi! My attr is {{attr}}
{{/each}}

答案 1 :(得分:0)

这个问题对ArrayControllers,CollectionViews,Models和ObjectControllers提出了一个重要且长期存在的问题。

在撰写本文时,我对Ember内部运作的了解有限。但是,我可以更简洁地将我的问题改写如下:

  

给定模型的ArrayController,CollectionView和实例控制器,如何利用ArrayController的itemControllerClass属性迭代其内容并将每个项目包装在一个itemController的唯一(即非单例)实例

事实证明这个问题是长期存在的,解决方案与@ jeremy-green相呼应,但我会扩展这里的事情。

首先关闭:封装问题的Ember支持线程:https://github.com/emberjs/ember.js/issues/1637

我认为那里的讨论非常明确地指出在某些情况下需要非单一控制器。

同样,这里是ArrayController的文档,它指示ArrayController上存在'itemController'属性:http://emberjs.com/api/classes/Ember.ArrayController.html#property_itemController

进一步了解文档,您还会注意到'lookupItemController'函数的存在:http://emberjs.com/api/classes/Ember.ArrayController.html#method_lookupItemController

这些函数的目的是将内容作为控制器的数组返回但是如何?

第一个要求是直接使用ArrayController作为循环中的内容。不幸的是,事情开始分崩离析。

您可能认为只能使用CollectionView

{{view myCollectionView controllerBinding=myArrayController}}

{{view myCollectionView contentBinding=myArrayController}}

但遗憾的是情况并非如此。在您在另一个Controller的路径上渲染Controller的情况下更是如此。 CollectionView不保留ArrayController与其'itemControllerClass`

之间的关系

正如@ jeremy-green指出的那样,实现这项工作的唯一方法是:

{{#each myFooArray itemController="foo"}}
  Hi! My attr is {{attr}}
{{/each}}

更完整的例子是:

<ol class="foo-item-list">
  {{#each controllers.foo_items}}
    <li>{{ view "foo" }}</li>
  {{/each}}
</ol>

其中App.FooItemsController已定义属性itemControllerlookupItemController

不幸的是,在这种情况下,我们失去了使用CollectionView的tagNameemptyView属性的好处。希望如果创建'ArrayView',它将为这种情况带来两全其美!