【问题标题】:yield in component that is called from an each helper从每个助手调用的组件中的产量
【发布时间】:2013-11-20 22:22:37
【问题描述】:

这是我的组件模板的一部分:

{{#each displayResults}}
  <li {{action addSelection this}} {{bindAttr class=\":result active\"}}>
  {{#if controller.template}}
    {{yield}}
  {{else}}
    <span class=\"result-name\">{{displayHelper controller.searchPath}}</span>
  {{/if}}
  <\/li>
{{/each}}

我希望用户能够自定义用于显示结果的 html。

问题是 {{yield}} 在 {{#each}} 助手中被调用,如果组件是这样声明的:

{{#auto-suggest source=controller.employees destination=controller.chosenEmployees}}
<span class=\"result-name\"><img src="img/small_avatar.png"/>{{fullName}}</span>
{{/auto-suggest}}

那么 {{#auto-suggest}} 之间的块没有组件中 {{#each}} 助手的上下文。

有什么我可以做的吗?或者事情就是这样?

【问题讨论】:

    标签: javascript ember.js


    【解决方案1】:

    更新

    现在ember 1.10 已经登陆,引入了一种称为块参数的新语法。所以不需要重写_yield 方法。例如,在您的组件模板中,您可以这样做:

    <ul>    
      {{#each item in source}}
        <li>
        {{! the component is being used in the block form, so we yield}}
        {{#if template.blockParams}}
          {{yield item}}
        {{! no block so just display the item}}
        {{else}}
          {{item}}
        {{/if}}
        </li>
      {{/each}}
    </ul>
    

    然后在使用组件时,您会使用as |var| 将参数传递给{{yield}}

    {{! no block, the component will just display the item}}
    {{auto-suggest source=model as |item|}}
    
    {{! in the block form our custom html will be used for each item}}
    {{#auto-suggest source=model as |item|}}
      <h1>{{item}}</h1>
    {{/auto-suggest}}
    

    Simple live example

    当然,您可以使用 {{yield name age occupation hobbies}} 生成任何变量,并在组件中捕获它们:

    {{#x-foo user=model as |name age occupation hobbies|}}
      Hi my name is {{name}}, I am {{age}} years old. Major of the times I am {{occupation}}, but also love to {{hobbies}}.
    {{/x-foo}}
    

    旧版本

    您可以覆盖Ember.Component 的默认_yield 方法,并将context: get(parentView, 'context') 更改为context: get(view, 'context')

    App.AutoSuggestComponent = Ember.Component.extend({
      _yield: function(context, options) {      
        var get = Ember.get, 
        view = options.data.view,
        parentView = this._parentView,
        template = get(this, 'template');
    
        if (template) {
          Ember.assert("A Component must have a parent view in order to yield.", parentView);      
          view.appendChild(Ember.View, {
            isVirtual: true,
            tagName: '',
            _contextView: parentView,
            template: template,
            context: get(view, 'context'), // the default is get(parentView, 'context'),
            controller: get(parentView, 'controller'),
            templateData: { keywords: parentView.cloneKeywords() }
          });
        }
      }
    });
    

    【讨论】:

      【解决方案2】:

      根据 Marcio Junior 的回答,您可以在不重新创建整个函数的情况下扩充 _yield。虽然不是透明地改变_yield 的行为,我还是建议你为你的组件添加一个选项。例如,

       {{#whatever-component useComponentContext=true}}
      

      在你的组件的 JavaScript 文件中:

        // duck-punch _yield to use the current view
        _yield: function(content, options) {
          var oldParentView = this._parentView;
      
          if (this.get('useComponentContext')) {
            // temporarily set _parentView to the view we want
            this.set('_parentView', options.data.view);
      
            // expose the original context via `_parent`
            options.data.view.get('context').set('_parent', oldParentView.get('context'));
          }
      
          // call the built-in _yield like normal
          var result = this._super.apply(this, arguments);
      
          // restore _parentView
          this.set('_parentView', oldParentView);
      
          return result;
        }
      

      有了这个,像

      {{!-- whatever-component.hbs --}}
      {{#each something in somethings}}
        <div {{bind-attr title=something.id}}>
          {{#with something}}
            {{yield}}
          {{/with}}
        </div>
      {{/each}}
      
      {{!-- some-view.hbs --}}
      {{#whatever-component.hbs}}
        <h1>{{id}}</h1>
        <p>{{someField}}</p>
        <div>{{_parent.theContextTheComponentIsBeingRenderedIn}}</div>
      {{/whatever-component.hbs}}
      

      将按预期工作

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-09-02
        • 2010-12-25
        • 2013-07-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多