1

How can I call inside a helper the equivalent to the Handlebars's helper {{component 'componentName' model=model}} to dynamically render components based on a programmatically changed componentName?

I'm using ember-cli 1.13.8, with Ember 2.0.1.

A bit of context

I have components called cs-widget-image, cs-widget-text, cs-widget-form that expect for a model widget based on its kind attribute.

So for a widget which its kind is image, I wanna render the component cs-widget-image, but I don't think that the logic to discover the name of the correct component should be knew by the model, so I'm not considering using the helper {{component widget.componentName}} on my view.

I think that the better would be have a helper that I can use on my views like:

{{#each manyTypesWidgets as |widget|}}
  {{widget-component widget.type model=widget}}
{{/each}}

On my mind, the helper widget-component would receive a widget model, and based on its attributes do a kind of "eval" and internally call the equivalent to {{component 'componentName' model=widget}}

Ex.: With widget = {id: 1, type: 'image'}

{{widget-component widget.type model=widget}}

should programmatically call the equivalent to HandleBars helper on template:

{{component 'cs-widget-image' model=widget}}

Disclaimer about a possible duplicate question

Before mark it as duplicate, I need to say that I really found some similar questions here on StackOverflow like: [1] [2] [3] [4] [5], but all the answers are based on an elderly version of Ember that didn't work anymore on Ember 2.0.1 and ember-cli 1.13.8.

Community
  • 1
  • 1
cefigueiredo
  • 738
  • 3
  • 12

2 Answers2

3

You can build a helper and put the logic of building the component name inside of it. Let's call the helper widget-name, you'd use it like this:

{{component (widget-name widget) model=widget}}

If the logic is as simple as appending the widget type to the end of cs-widget- the following should do the trick:

{{component (concat "cs-widget-" widget.type) model=widget}}

I believe your widget-component approach is more complex, because you would have to have a computed property with the logic and then bind that in a {{component call. I hope the two suggestions are helpful :)

locks
  • 6,537
  • 32
  • 39
  • That it's a perfect workaround, and I also got it suggested on Ember slack. Anyway, I'm asking for the possibility to make a helper with a behavior similar to {{component}} to call it programmatically. Just to encapsulates all the logic on manipulating the name of the component. – cefigueiredo Oct 23 '15 at 13:27
1

Won't this work for you?

//JS

widgetsWithTemplates : Ember.computed.map('manyTypesWidgets', function(widget) {
   widget.set('componentName', 'cs-widget-' + widget.get('type')); 
})

And in the template you just call the component by componentName property:

//HBS 

  {{#each manyTypesWidgets as |widget|}}
       {{widget.componentName model=widget}}
  {{/each}}
kristjan reinhold
  • 2,038
  • 1
  • 17
  • 34
  • Also an easy way would be to make a common-component. When calling out the common-component you specify dynamic layoutName="xx" and the common-component has imported functionality of your components. So the actions and observers would work in common component. – kristjan reinhold Oct 23 '15 at 06:37
  • Actually I'm purging the common-component way to have just the specific component called by a "dynamic component caller" helper. – cefigueiredo Oct 23 '15 at 13:29
  • Anyway, I don't wanna have any ember computed on the model/controller/top-level component answering which the name of the specific widget component. Just because it is not their responsibility. I'm more into the @locks answer, but preferably in a way that a helper that call `{{component 'componentName'}}` programmatically in a way that I can manipulate the componentName on my will – cefigueiredo Oct 23 '15 at 13:31