Как я могу динамически активировать динамический компонент с помощью переменной?

Предположим, что у меня есть массив объектов виджетов на моем контроллере, и каждый объект виджета имеет переменную-член, которой назначено имя класса компонента. Как я могу заставить свой шаблон вызывать этот компонент?

//widgets[0].widget.componentClass="blog-post"

{{#each widget in widgets}}
    {{widget.componentClass}}
{{/each}}

Очевидно, что приведенный выше пример просто выплескивает ряд строковых версий классов компонентов виджета. Это, однако, работает (пока вы все правильно настроили):

//widgets[0].widgets.viewClass="blogPost"

{{#each widget in widgets}}
    {{view widget.viewClass}}
{{/each}

Это была наша предыдущая реализация, но мы были недовольны этим. В настоящее время мы используем специальный тег {{renderWidget...}} с помощником handlebars, как описано здесь: Вызов Handlebars {{render}} с именем переменной. У вспомогательного помощника по умолчанию есть аналогичная проблема, где он не будет вызывать рендеринг в содержимом имени переменной. Я бы хотел написать специальный помощник handbars компонента, но я даже не могу понять, с чего начать. Спасибо.

Ответы

Ответ 1

В Ember 1.11 новый component помощник позволяет вам сделать это:

{{#each widget in widgets}}
  {{component widget.componentClass}}
{{/each}}

На сегодняшний день, 19 января 2015 года, 1.11 не является стабильным выпуском, но эта функция находится в канареечной версии.

Ответ 2

Я пробовал это и, похоже, сработал, но его просто догадки с моей стороны:

Ember.Handlebars.registerHelper('renderComponent', function(componentPath, options) {
  var component = Ember.Handlebars.get(this, componentPath, options),
      helper = Ember.Handlebars.resolveHelper(options.data.view.container, component);

  helper.call(this, options);

});

и вы используете его таким же образом:

{{#each widget in widgets}}
  {{renderComponent widget.componentClass widget=widget}}
{{/each}}

Ответ 3

Похоже, я столкнулся с теми же проблемами, что и вы. Все компоненты зарегистрированы как помощники верхнего уровня, а это значит, что вы можете сделать аналогичный метод с тем, который вы связали с созданием помощника руля, который выполняет поиск. Вот так:

Ember.Handlebars.registerHelper('lookup', function(component, options) {
  component = Ember.Handlebars.get(this, component, options);
  Ember.Handlebars.helpers[component].call(this, options);
});

Затем в вашем шаблоне:

{{#each widget in widgets}}
  {{lookup widget.componentClass}}
{{/each}}

Здесь jsbin с рабочим примером: http://jsbin.com/ucanam/2482/edit

Надеюсь, что это поможет!

- изменить -

По какой-то причине новая версия рулей делает невозможным вызов помощников из других помощников. Вместо этого вы можете искать шаблон через глобальный Ember.TEMPLATES. Я обновил JSBin, чтобы использовать этот метод.

Вы также можете получить шаблон с помощью options.data.view.templateForName(component), но он чувствует себя немного более хрупким, чем Ember.TEMPLATES.

- изменить 2 -

Снова изменилось. Ember.Handlebars.resolveHelper теперь правильный способ сделать это. См. Ответ @StrangeLooper.

Ответ 4

Если вы используете Ember CLI и Coffeescript, здесь приведена версия для этого. Создайте следующий файл в app/helpers/render-component.coffee:

renderComponent = (componentPath, options)->
  helper = Ember.Handlebars.resolveHelper(options.data.view.container, componentPath)
  helper.call this, options

`export { renderComponent }`
`export default Ember.Handlebars.makeBoundHelper(renderComponent)`

Оттуда вы можете вызвать {{render-component "foo-bar"}} из шаблона.

Поскольку экосистема Ember постоянно меняется, вот версия, на которую я ее протестировал:

  • Ember-CLI v0.0.43
  • Ember v1.7.0
  • Handlebars 1.3.0