# Dynamically render polymorphic component

**URL:** <https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184>\
**Category:** Uncategorized\
**Created:** [October 30, 2013, 6:30pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184 "2013-10-30T18:30:21Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![rlivsey](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/rlivsey/32/14737_2.png) [@rlivsey](https://discuss.emberjs.com/u/rlivsey)\
**Post date:** [October 30, 2013, 6:30pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/1 "2013-10-30T18:30:21Z")

</div>

I’ve got a list of polymorphic items, each of which corresponds to a different component which needs to be displayed.

The type of the item can change at any time, at which point the component needs to change.

Initially I just had a bunch of `{{#if...}}` statements like:

```
{{#if isBlue}} {{blue-item item=item ...}} {{/if}}
{{#if isRed}} {{red-item item=item ...}} {{/if}}
{{#if isGreen}} {{green-item item=item ...}} {{/if}}

```

This works, but is rather unwieldy especially as each one has a bunch of attributes & event bindings, all of which are the same for each component type. There’s currently 7 different types and this will only grow over time, with the `{{if}}`'s that means there’s 7 lots of metamorph tags and associated overhead. There will be quite a few items in this list so I’d like the overhead to be as little as possible.

I’ve tried to tidy this by creating a helper which renders the right component type:

```
Ember.Handlebars.registerBoundHelper 'component-for-type', (type, options) ->
  name = switch type
    when 'red' then "red-item"
    when 'blue' then "blue-item"
    when 'green' then "green-item"
    else throw new Ember.Error("no component found for '#{type}'")

  helper = Ember.Handlebars.resolveHelper(options.data.view.container, name)
  helper.call(this, options)

```

That means I can replace all the `{{if}}`'s with one:

```
{{component-for-type item.type 
    item=item 
    selectedItem=selectedItem
    onSelect="select" 
    onChange="change" 
    ... 
}}

```

This works for the initial render, but when the items type changes it blows up because the helper is trying to call `view.appendChild` on an already rendered view which isn’t allowed.

Another approach I’ve thought of is to render a partial based on the item type, I think that’ll get rid of all the ifs, but leaves me with 7 almost identical templates to maintain.

Anyone any thoughts?

---

<div class="post-metadata">

**Author:** ![davidjnelson](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/davidjnelson/32/15274_2.png) [@davidjnelson](https://discuss.emberjs.com/u/davidjnelson)\
**Post date:** [November 17, 2013, 10:20pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/2 "2013-11-17T22:20:08Z")

</div>

Fantastic question. Sorry I don’t have an answer. I love the way you think!

---

<div class="post-metadata">

**Author:** ![davidjnelson](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/davidjnelson/32/15274_2.png) [@davidjnelson](https://discuss.emberjs.com/u/davidjnelson)\
**Post date:** [November 18, 2013, 2:25am UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/3 "2013-11-18T02:25:39Z")

</div>

This looks like it will solve your problem: [javascript - how can I invoke an ember component dynamically via a variable? - Stack Overflow](http://stackoverflow.com/questions/18972202/how-can-i-invoke-an-ember-component-dynamically-via-a-variable)

---

<div class="post-metadata">

**Author:** ![rlivsey](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/rlivsey/32/14737_2.png) [@rlivsey](https://discuss.emberjs.com/u/rlivsey)\
**Post date:** [November 18, 2013, 10:12am UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/4 "2013-11-18T10:12:44Z")

</div>

Thanks @davidjnelson, that’s doing basically the same as my original example except I’m using the new API for component lookup. It works fine for the initial render, but you can’t then change the component type and re-render without it exploding.

At the moment I’m using a `ContainerView` and replacing the `childViews` with the new component when the type changes. It works, but it’s a little clunky, especially as I’m using the private `_Metamorph` helper. Would be nice to have a baked in way of doing this - I’ll dig deeper and see about tidying it up into something I can turn into a pull request.

```
ComponentForTypeView = Ember.ContainerView.extend Ember._Metamorph,
  item: null
  onDelete: "onDelete"
  onSelect: "onSelect"

  childViews: (->
    [@componentForType()]
  ).property()

  changeChild: (->
    @clear()
    @pushObject(@componentForType())
  ).observes("item.type")

  componentForType: ->
    type = @get("item.type")

    container = @get('container')
    componentLookup = container.lookup('component-lookup:main')
    itemComponent = componentLookup.lookupFactory(type, container)

    itemComponent.create
      item: @get("item")
      onDelete: @get("onDelete")
      onSelect: @get("onSelect")

Ember.Handlebars.helper('component-for-type', ComponentForTypeView)

```

---

<div class="post-metadata">

**Author:** ![groumanis](https://avatars.discourse-cdn.com/v4/letter/g/c68b51/32.png) [@groumanis](https://discuss.emberjs.com/u/groumanis)\
**Post date:** [April 22, 2014, 7:01pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/5 "2014-04-22T19:01:51Z")

</div>

Any update on this? I am currentlyrunning into the same issue in which I’d like to dynamically render components based off of some item value.

---

<div class="post-metadata">

**Author:** ![billdami](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/billdami/32/4922_2.png) [@billdami](https://discuss.emberjs.com/u/billdami)\
**Post date:** [May 2, 2014, 2:08pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/6 "2014-05-02T14:08:42Z")

</div>

I’m attempting to use [this stackoverflow solution](http://stackoverflow.com/a/21590414/192694) as mentioned by @davidjnelson, however I am unsure on how to modify the options passed to the resolved component, in order to set some properties that the component is expecting, as well as how to set that content that will be injected in the component’s `{{yield}}`.

I’n my case, I am dynamically constructing a web form by iterating over an array of field definition objects, that contain the field name, field type (e.g. text, select, checkbox, ect), its label, whether its required, ect. The field’s type is what determines what component should be resolved, but then I must modify the `options` (I think?) in order to pass it things like the field value. Also, I must be able to set what gets rendered in the component’s `{{yield}}`, as my form field components utilize it for the label text.

Here is a simplified example of one of my form field components to better illustrate my scenario:

```
templates/components/form-input.hbs

<label {{bind-attr for=inputId}} class="control-label">{{yield}}</label>
{{input value=value type=type id=inputId class="form-control"}}
<div class="form-error-text">{{errorMsg}}</div>

```

Here’s how I render it regularly, in a non-dynamic way:

```
{{#form-input value=firstName required=true}}{{_ "First Name"}}{{/form-input}}

```

Here’s how I need to render it dynamically:

```
{{#each field in editableFields}}
    {{renderComponent content field}}
{{/each}}

```

Where `content` is the controller’s associated model that contains attributes that map directly to the names of the fields in `editableFields`, i.e. `model.get(field.get('name'))` would get the value from the model that needs to be rendered for that `field`.

So essentially I need to be able to set the `value` and `required` properties and the content between the `{{form-input}}` block tags dynamically from the `renderComponent` helper in the stackoverflow answer.

---

<div class="post-metadata">

**Author:** ![billdami](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/billdami/32/4922_2.png) [@billdami](https://discuss.emberjs.com/u/billdami)\
**Post date:** [May 2, 2014, 7:46pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/7 "2014-05-02T19:46:06Z")

</div>

So after some trial and error, I implemented the pieces I was missing in the `renderComponent` (or `renderField` rather in my case) helper and they seem to be working, however I just wanted to post my solution here, just to see if anyone could give some feedback, in case I am overlooking anything or not following best practices, ect.

```
Ember.Handlebars.registerBoundHelper('renderField', function(record, fieldCfg, options) {
    var helper;

    options.hash.value = record.get(fieldCfg.get('name')); 
    options.hash.required = fieldCfg.get('required');
    
    options.fn = function() {
        return fieldCfg.get('label');
    };        

    helper = Em.Handlebars.resolveHelper(
        options.data.view.container, 
        fieldCfg.get('componentName')
    );

    helper.call(this, options);
});

```

---

<div class="post-metadata">

**Author:** ![rlivsey](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/rlivsey/32/14737_2.png) [@rlivsey](https://discuss.emberjs.com/u/rlivsey)\
**Post date:** [May 2, 2014, 9:23pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/8 "2014-05-02T21:23:44Z")

</div>

Hi @billdami I’ve tried something very similar, it works on the first render but not when the type changes.

When the component type changes (assuming that’s bound), you get an error saying you can’t `appendChild` outside of `render`.

I’m currently still using my `ContainerView` approach above, but I’m sure there’s a better way. I’m holding off any further investigation until HTMLbars comes in because I think a fair bit is changing in the view side of things!

---

<div class="post-metadata">

**Author:** ![billdami](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/billdami/32/4922_2.png) [@billdami](https://discuss.emberjs.com/u/billdami)\
**Post date:** [May 2, 2014, 9:56pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/9 "2014-05-02T21:56:32Z")

</div>

@rlivsey yeah I saw that you mentioned that limitation in your previous posts, but luckily in my case the types are static, and won’t ever change. I just mainly wanted to make sure the way I had implemented the other parts of my `renderField` helper was done correctly, namely, setting of additional option parameters and the content to output in the resolved component’s `{{yield}}` via `options.fn`, as I couldnt really find any hard documentation on those aspects.

---

<div class="post-metadata">

**Author:** ![Terion](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/terion/32/15788_2.png) [@Terion](https://discuss.emberjs.com/u/Terion)\
**Post date:** [May 14, 2014, 11:29am UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/10 "2014-05-14T11:29:51Z")

</div>

Components with dynamic layout can be used for this. For example:

```
App.EditFieldComponent = Ember.Component.extend
model: {}
field: {}

layoutName: (->
    field = 'text'
    switch @field?.type
        when 'longtext' then field = 'textarea'
        when 'enum' then field = 'select'

    "components/edit-field/" + field + "-field"
).property('field')

name: (-> @field?.name).property('field')
value: (-> @get('model')?.get(@field?.name)).property('model', 'field')
bind: (->
    @model.set @field.name, @value
).observes('value')

```

When “field” changes, layout also changes and component updates live. Templates with inputs should contain input helpers or use attr bindings, then full two-way binding will be supported due to observer in component

---

<div class="post-metadata">

**Author:** ![shlonny](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/shlonny/32/9052_2.png) [@shlonny](https://discuss.emberjs.com/u/shlonny)\
**Post date:** [May 28, 2014, 3:22pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/11 "2014-05-28T15:22:19Z")

</div>

@Terion I’m still trying to wrap my head around the example you provided. Could you post an example of the HTML that would use your component?

---

<div class="post-metadata">

**Author:** ![rlivsey](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/rlivsey/32/14737_2.png) [@rlivsey](https://discuss.emberjs.com/u/rlivsey)\
**Post date:** [October 15, 2014, 8:23pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/12 "2014-10-15T20:23:02Z")

</div>

I’ve made an ember-cli addon which might be useful:

[https://github.com/MinuteBase/ember-dynamic-component](https://github.com/MinuteBase/ember-dynamic-component)

eg:

```handlebars
{{dynamic-component type=type onClick="thingClicked" value=something}}

```

hth

---

<div class="post-metadata">

**Author:** ![Sharavsambuu\_Gu](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/sharavsambuu_gu/32/15399_2.png) [@Sharavsambuu\_Gu](https://discuss.emberjs.com/u/Sharavsambuu_Gu)\
**Post date:** [October 17, 2014, 3:56pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/13 "2014-10-17T15:56:05Z")

</div>

thank you for sharing!

---

<div class="post-metadata">

**Author:** ![alpacaaa](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/alpacaaa/32/14390_2.png) [@alpacaaa](https://discuss.emberjs.com/u/alpacaaa)\
**Post date:** [November 2, 2014, 10:43am UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/14 "2014-11-02T10:43:53Z")

</div>

This is quite cool dude! I’ve been waiting for something like this. Will keep an eye on development.

---

<div class="post-metadata">

**Author:** ![TrevTheDev](https://avatars.discourse-cdn.com/v4/letter/t/edb3f5/32.png) [@TrevTheDev](https://discuss.emberjs.com/u/TrevTheDev)\
**Post date:** [November 14, 2014, 2:32am UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/15 "2014-11-14T02:32:17Z")

</div>

Awesome component thank you. However it no longer works in Ember 1.9

I resolved by removing childViews and adding :

```
setChild: function(){
  this.clear();
  this.pushObject(this.componentForType());
}.on('init'),

```

---

<div class="post-metadata">

**Author:** ![rlivsey](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/rlivsey/32/14737_2.png) [@rlivsey](https://discuss.emberjs.com/u/rlivsey)\
**Post date:** [November 14, 2014, 3:28pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/16 "2014-11-14T15:28:37Z")

</div>

I released v0.0.2 which fixes this a few days ago, so you should just need to update it via npm.

---

<div class="post-metadata">

**Author:** ![miguelcobain](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/miguelcobain/32/15323_2.png) [@miguelcobain](https://discuss.emberjs.com/u/miguelcobain)\
**Post date:** [November 18, 2014, 12:44pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/17 "2014-11-18T12:44:15Z")

</div>

@rlivsey I know Ember 2.0 is moving towards components, and that they’re taking a bigger and bigger role. So, `ember-dynamic-component` is great. However, I can’t wrap my head around my use case.

I have a section where I want to display a list of tasks with their own type. Each type has it’s own template which allows the user edit the task.

I could create a component for each task type, but in the templates I need access to the store, for example. The “Repair Task” type needs a list of repair types from the store, to let the user select one of them.

I don’t feel comfortable accessing the store from a component. It is clearly not idiomatic and not the goal of a component. Also, i don’t feel comfortable doing `{{dynamic-component type=t.taskType value=t repairTypes=repairTypes}}`, i.e passing repairTypes to _all_ of our task components. Just because _all_ the other task types don’t require the repair types at all!

My intuition tells me that the ideal approach would be to use the render helper dynamically. Then, in each controller, I could access the store only if that template was rendered. However, even in [this issue](https://github.com/emberjs/ember.js/issues/4777) @rwjblue and @mixonic encourage moving towards components.

I feel like we could loose flexibility in that way.

---

<div class="post-metadata">

**Author:** ![acorncom](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/acorncom/32/12198_2.png) [@acorncom](https://discuss.emberjs.com/u/acorncom)\
**Post date:** [February 24, 2015, 12:58am UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/18 "2015-02-24T00:58:54Z")

</div>

For the record here, this issue ([https://github.com/emberjs/ember.js/pull/10093](https://github.com/emberjs/ember.js/pull/10093)) will end up building a `component` helper that does what we’re after here.

Looks like it’s supposed to hit in Ember 1.11. Thanks for the work on the component @rlivsey!

---

<div class="post-metadata">

**Author:** ![lifeinafolder](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/lifeinafolder/32/11110_2.png) [@lifeinafolder](https://discuss.emberjs.com/u/lifeinafolder)\
**Post date:** [July 21, 2015, 11:52pm UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/19 "2015-07-21T23:52:11Z")

</div>

> [@miguelcobain](#):
>
> Also, i don’t feel comfortable doing {{dynamic-component type=t.taskType value=t repairTypes=repairTypes}}, i.e passing repairTypes to all of our task components. Just because all the other task types don’t require the repair types at all!

I would like to understand how is this tackled with the `{{component}}` helper? All components having the same API sounds limiting.

---

<div class="post-metadata">

**Author:** ![jasonmit](https://sea1.discourse-cdn.com/flex019/user_avatar/discuss.emberjs.com/jasonmit/32/182_2.png) [@jasonmit](https://discuss.emberjs.com/u/jasonmit)\
**Post date:** [July 22, 2015, 3:39am UTC](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184/20 "2015-07-22T03:39:29Z")

</div>

> [@lifeinafolder](#):
>
> All components having the same API sounds limiting.

A single API interface across various types is polymorphism. In your case, you would be dealing with types that are not polymorphic so some conditional switch or factory-like behavior would be involved I am guessing.

[Next page](https://discuss.emberjs.com/t/dynamically-render-polymorphic-component/3184.md?page=2)
