如何从Ember中的模板调用控制器功能?

Bri*_*sio 12 ember.js

假设我有一个迭代一组项目的模板,我想调用一个特定于控制器的每个项目的函数,而不是模型级别的问题:

{{#each people as |person|}}
  icon name: {{findIconFor(person)}}
{{/each}}
Run Code Online (Sandbox Code Playgroud)

我想findIconFor在控制器中定义,因为这是特定视图的特定内容.

export default Ember.Controller.extend({
  findIconFor: function(person) {
    // figure out which icon to use
  }
);
Run Code Online (Sandbox Code Playgroud)

但这不起作用. 模板无法编译.解析错误:期待'STRING','NUMBER','ID','DATA',得到'INVALID'

这样做的"余烬方式"是什么?

Arn*_*tor 12

因为我几乎整天都在类似的问题上花了我的解决方案.

因为Ember由于某种原因只是不允许你直接从模板运行控制器功能(这是荒谬的,并以一些非常愚蠢的方式绑你的手,我不知道谁在地球上认为这是一个好主意.. .)对我来说最有意义的是创建一个通用的自定义帮助程序,它允许你从模板运行函数:)这里的问题是你应该总是将当前作用域("this"变量)传递给帮手.

所以助手可能是这样的:

export default Ember.Helper.helper(function([scope, fn]) {
    let args = arguments[0].slice(2);
    let res = fn.apply(scope, args);
    return res;
});
Run Code Online (Sandbox Code Playgroud)

然后,您可以在控制器中创建要运行的功能,例如:

testFn: function(element){
    return element.get('name');
}
Run Code Online (Sandbox Code Playgroud)

然后在您的模板中,您只需使用自定义帮助程序调用它:

{{#each items as |element|}}
    {{{custom-helper this testFn element}}}
{{/each}}
Run Code Online (Sandbox Code Playgroud)

帮助器的前两个参数应始终为"this"和要运行的函数的名称,然后您可以根据需要传递多个额外的参数.


编辑:无论如何,每当你认为你需要这样做时,你应该考虑是否更好地创建一个新的组件(它将在90%的情况下)

  • "这太荒谬了,用一些非常愚蠢的方式将你的双手绑在一起......"这是我沮丧的声音.看起来像框架应该处理的简单事情. (2认同)

jnf*_*rle 8

我在控制器中使用了一个计算属性:

iconPeople: Ember.computed('people.@each', function(){
  var that = this;
  return this.get('people').map(function(person){
    return {
      'person': person,
      'icon': that.findIconFor(person)
    };
  });
})
Run Code Online (Sandbox Code Playgroud)

现在你可以从中获取图标{{person.icon}}和名称{{person.person.name}}.您可能希望改进(并且代码未经测试),但这是一般的想法.

  • 您不仅要监听人员阵列本身(即不同的阵列)的变化,还要监听阵列内容的变化. (2认同)