Skip to content Skip to sidebar Skip to footer

How Can I Yield Multiple Pieces Of Content Into An Ember.js Component Template?

The goal is to define a structure of HTML that has more than one block of content that is declared by the caller. For example, a header, body, and content. The resulting markup sho

Solution 1:

As of ember v1.10, yield accepts parameters. However handlebars doesn't yet allow for inline comparisons of variable values. By defining some properties on the component, we can get pretty close to what rails does.

Per the above example, the component's template would look like:

<header>{{yield header}}</header><divclass="body">{{yield body}}</div><footer>{{yield footer}}</footer>

And the component definition would resolve the variable arguments to the yield statements:

export default Ember.Component.extend({
  header: {isHeader: true},
  footer: {isFooter: true},
  body:   {isBody: true}
});

This means that {{yield header}} is actually yielding an object {isHeader: true} to the consuming template. So we can use a nested if/else structure to declare the three sections like this:

{{#my-comp as |section|}}
  {{#if section.isHeader}}
    My header
  {{elseif section.isBody}}
    My body
  {{elseif section.isFooter}}
    My footer
  {{/if}}
{{/my-comp}}

Solution 2:

The previous reply may be out-to-date.

There is an accepted RFC for this problem; the Named Templates Block API will support passing multiple blocks to a component.

As of Ember 2.3, Contextual components allows another approach to this case:

Split your component into multiple subcomponents and pass the subcomponents back to the component as block parameters; this setup allows to set the content of each subcomponent block.

Check out the Twiddle - full example.

// my-component.js

{{yield (hash
   header = (component 'my-header')
   content = (component 'my-content')
   footer = (component 'my-footer')
)}}
{{#unless hasBlock}}
   {{my-header}}
   {{my-content}}
   {{my-footer}}    
{{/unless}}

// my-{header/content/footer}.js

{{#if hasBlock}}
   {{yield}}
{{else}}
   Default xxxxx
{{/if}}

In this case, you could use the default component content or pass the specific content to any subcomponent like:

{{my-component}}



{{#my-component as |f|}}
  {{f.header}}
  {{#f.content}}
    Custom content
  {{/f.content}}
  {{f.footer}}
{{/my-component}}


{{#my-component as |f|}}
  {{#f.header}}
     Custom header
  {{/f.header}}
  {{#f.content}}
     Custom content
  {{/f.content}}
  {{#f.footer}}
     Custom footer
  {{/f.footer}}
{{/my-component}}

This solution does not force the component API/structure, then the component could be wrongly used if a subcomponent is omitted, added multiple times, or have the wrong order, in these cases the component will generate an undesired content.

Check out the Twiddle - full example.

Post a Comment for "How Can I Yield Multiple Pieces Of Content Into An Ember.js Component Template?"