Как я могу динамически активировать динамический компонент с помощью переменной?
Предположим, что у меня есть массив объектов виджетов на моем контроллере, и каждый объект виджета имеет переменную-член, которой назначено имя класса компонента. Как я могу заставить свой шаблон вызывать этот компонент?
//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