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

纵然是瞬间 提交于 2019-11-27 13:47:53

问题


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?


回答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>
<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}}



回答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.



来源:https://stackoverflow.com/questions/30282377/how-can-i-yield-multiple-pieces-of-content-into-an-ember-js-component-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!