How can I yield multiple pieces of content into an ember.js component template?

aceofspades picture aceofspades · May 17, 2015 · Viewed 7.4k times · Source

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 should be:

<header>My header</header>
<div class="body">My body</div>
<footer>My footer</footer>

The template instantiating the component would define each of the three sections, My header, My body, and My footer.

With Ruby on Rails, you would use content_for :header to capture the header content from the caller, and yield :header to interpolate it.

Is this possible in ember.js?

Answer

aceofspades picture aceofspades · May 17, 2015

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>
<div class="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
  {{else if section.isBody}}
    My body
  {{else if section.isFooter}}
    My footer
  {{/if}}
{{/my-comp}}