如何在Emberjs中的控制器之间传递事件?更新:如何在Ember中设计自动完成

Mat*_*ola 7 ember.js

方案:一种自动完成构件与它自己的控制器和视图,使得其为可,一旦它被移出被渲染到与{{渲染"自动完成"}}或可能新的{{控制}}辅助的任何其它视图的模块部件实验阶段.为了使自动完成独立于其他所有内容,它不应该知道父控制器或选择项目时发生的操作.

我已经试图找出如何使用Ember.Evented混入,这样我可以触发从自动完成的事件如itemSelected然后可以冒泡并通过父视图或控制器捕获.

因此,一如既往,缺乏Ember文档.特别是当谈到Ember.Evented.(为了公平起见文档已经走过了很长的路要走,但我还是希望有更多的.他们说,约定优于配置不提供约定!)不管怎么说,足以抱怨,文档显示余烬事件触发的通用对象工作,我发现这个职位它进入更深入一点:EmberJs是否支持发布/订阅者事件模式?但我认为一个更真实的例子,包括控制器,视图,路由和自动填充等组件会很棒.

我认为这些类型的事件被认为是视图的责任,但是没有用,所以我也将mixin放在控制器上.当你看到jsFiddle时,这是有意义的

在其中你会看到一个假的自动完成控制器,它只是从一个夹具中获取一组静态内容,并显示每个项目的两个按钮,你可以点击它们从视图或控制器触发一个事件.在一个实际例子中,将观察文本框中的输入,并且将更新内容以基于输入呈现不同的建议,但这对于该示例并不重要.

的jsfiddle:http://jsfiddle.net/wCfb9/ 我最怀疑这些行:this.on("myEvent", this.addItem); 因为触发事件的功能显然被调用,但它好像事件不传播或索引控制器和视图不实际上正确设置以响应事件.

以下是主要问题:

  1. 我需要更改什么才能使索引控制器响应自动完成触发的事件?

  2. 实现这一目标的MVC最合适的方法是什么?应该在视图/控制器上触发/接收?

  3. 有一个更好的方法吗?

旁注:我目前的解决方案是needs: ["index"]在自动完成控制器中添加一个而不是触发事件,我只是从自动完成控制器显式调用索引控制器中的方法.这有很多问题,首先是控制器之间的紧密耦合,如果自动完成被认为影响多个控制器或者在别处重新使用并且必须重新配置等,则不能很好地扩展.

希望我能够清楚地解释清楚.所有帮助表示赞赏.

Mik*_*tti 3

哇,好问题。

为了使自动完成独立于其他一切,它不应该知道父控制器或选择某个项目时会发生什么操作。

是的,我认为你在努力使事情尽可能孤立方面走在正确的道路上。

有一个更好的方法吗?

我认为是的,正确的方法是使用 RC6 中引入的新“组件”功能。有关详细信息,请参阅Ember 组件 API 文档

使用组件方法,您可以实现独立于父控制器的自动完成以及选择项目时发生的情况的目标。它与内置 Ember.Select 视图的操作方式非常接近。例如:

{{app-autocomplete items=model selectedItem=selectedPerson}}
Run Code Online (Sandbox Code Playgroud)

在这里,我设置了自动完成的项目和 selectedItem 属性以绑定到当前控制器上的值。app-autocomplete 不知道这些绑定的另一侧是什么,也不知道当值发生变化时调用者将如何反应。然后,您的索引控制器可以观察它自己的 selectedPerson 属性,并在其更改时做出反应。像这样的东西:

App.IndexController = Ember.ArrayController.extend({
  selectedPerson: null,
  selectedPersonDidChange: function() {
      Ember.Logger.log("Index.contoller addItem: ", this.get('selectedPerson').toString());
  }.observes('selectedPerson'),
});
Run Code Online (Sandbox Code Playgroud)

该组件也非常简单。它期望它的items属性包含一组带有 a 的对象name,当单击一个对象时,它会设置它自己的selectedItem属性。

<script type="text/x-handlebars" id="components/app-autocomplete">
  {{input}}
  {{#each item in items}}
    <li><button {{action itemSelected item}}>{{item.name}}</button></li>
  {{/each}}
</script>

App.AppAutocompleteComponent = Ember.Component.extend({
itemSelected: function (item) {
  this.set("selectedItem", item);
      Ember.Logger.log("component.itemSelected: myEvent triggered wit h: ", item.toString());
}
});
Run Code Online (Sandbox Code Playgroud)

完整示例在这里: http: //jsfiddle.net/dKUf4/