Выход в компоненте, который вызывается из каждого помощника

Это часть моего шаблона компонента:

{{#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}} вызывается while в помощнике {{#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}} в компоненте.

Есть ли что-нибудь, что я могу сделать, или это так, как есть?

Ответ 1

UPDATE

Теперь, когда Простой живой пример

Конечно, вы можете получить любые переменные, используя {{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}}

ДЛЯ СТАРЫХ ВЕРСИЙ

Вы можете переопределить метод _yield по умолчанию, Ember.Component и изменить 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}}

будет работать как ожидалось