James A. Rosen
James A. Rosen

Reputation: 65242

How do I invoke Ember's component helper programmatically?

I have a list of foos:

[
  { name: 'Foo 1' type: 'important' },
  { name: 'Foo 2' type: 'normal' },
  { name: 'Foo 3' type: 'purple' }
]

I want to render that list, but some of them have special handling -- not just a class, but entirely different markup.

My first instinct would be to use the component helper:

{{#each foos as |foo|}}
  {{component (join 'foo-' foo.type) foo=foo}}
{{/each}}

The downside to that is that I must define a component for each type and the server may send me new types that I don't know about. So I'd like to fall back to a basic foo-generic component if the foo-${type} component isn't defined.

To do that, I figured I'd create a helper:

{{#each foos as |foo|}}
  {{foo-entry foo}}
{{/each}}

// app/helpers/foo-entry.js
Ember.Helper.helper(function([ foo ]) {
  // ...
});

But I'm left with two questions:

  1. how do I get a container inside that helper so I can check whether component:foo-${foo.type} exists?
  2. how do I invoke the component helper from within another helper?

Upvotes: 0

Views: 152

Answers (1)

James A. Rosen
James A. Rosen

Reputation: 65242

I think I can do it with a component instead of a helper:

// app/pods/foo-entry/component.js
export default Ember.Component.extend({
  tagName: null,

  foo: null,

  componentName: Ember.computed('foo.type', function() {
    const type = this.get('foo.type');

    const exists =
      this.container.lookupFactory(`component:foo-${type}`) != null ||
      this.container.lookupFactory(`template:foo-${type}`) != null;

    return exists ? `foo-${type}` : 'foo-generic';
  })
})

{{!-- app/pods/foo-entry/template.hbs --}}
{{component componentName foo=foo}}

Upvotes: 4

Related Questions