Creating a wrapper template for a component


#1

Dear Emberists

I’ve got a data dashboard type of setup with several components that display charts and other Data-driven analytics.

I’m trying to determine an easy way of wrapping all my components in a generic loading indicator (with a “no data available” message where applicable.

Here are the desired states:

Loading:

Loaded:

No Data:

This is a pattern we use over and over and so far we’re reusing a template:

{{loading-overlay isVisible=isLoading}}
{{#if data}}

{{!-- {{YOUR_COMPONENT_HERE}} --}}

{{else}}
  {{#unless isLoading}}
    {{loading-overlay message="Data not available"}}
  {{/unless}}
{{/if}}

Copy and pasting every single time we need a different component.

We’re trying to think of a a way to do this more efficiently, but the way Components and Views work, we’re running into issues. So far, the best (but most difficult) solution I’ve come up with is to generate the components automatically and use a view helper:

{{loading-overlay isVisible=isLoading}}
{{#if title}}<h3>{{title}}</h3>{{/if}}
{{#if data}}
{{view childComponent}}
{{else}}
  {{#unless isLoading}}
    {{loading-overlay messageTranslation="chart.noData"}}
  {{/unless}}
{{/if}}

and in the code something like:

  myComponent: ( ->
    @container.lookupFactory("component:my-awesome-chart").createWithMixins
      __parent: @
      model: Ember.computed.oneWay("__parent.model")
      layout: @container.lookup("template:components/impulse-sortable-list") ## Very important for some crazy reason.
  ).property()

Finally it’s like

{{wrapper-component childComponent=myComponent}} and we’re off to the races.

However this has raised few eyebrows around the office. Does it have to be this way? Is there any way to simply wrap a component inside another without such ugliness?


#2

Guys: This question is obviously a use-case for {{yield}} I’m sorry for all the trouble.

By way of explanation, this comes after some considerable refactor and the old way of doing things was a bit more complicated.


#3

Something you may wish to use if you need to pass information from the wrapper to child components.

parent-component.hbs

{{yield parentsData}}

using-components.hbs

{{#parent-component as |parentsData|}}
   {{child-component parentData=parentsData}}
{{/parent-component}}