8

I have a custom view that I've created in Ember. I really love the {{yield}} helper to allow me to control the 'bread' of the sandwich. However, what I'd like to do now, is create a 'double decker' sandwich, and have a view with more than 1 yield in it, or at the very least be able to parameterize which template to use in the 2nd yield.

so for example:

layout.hbs

<div>
    <div class="header">Header Content</div>
    <div class="tab1">
        Tab 1 Controls.
        <input type="text" id="common1" />
        {{yield}}
    </div>
    <div class="tab2">
        Tab 2 Controls.
        <input type="text" id="common2" />
        {{yield second-template}} or {{template second-template}}
    </div>
</div>

app.js

App.MyDoubleDeckerView = Ember.View.extend({
    layoutName:"layout',
    templateName:"defaultTemplate", 
    "second-template":"defaultSecond"
});

App.MyExtendedDoubleDecker = App.MyDoubleDeckerView({
    templateName:"myTemplate", 
    "second-template":"mySecondTemplate"
});

is there any way of doing something like this? What I love about the views in ember is the ability to centralize & extend views which allows me to keep the things that are common among all the views in one place...

bantic
  • 4,886
  • 4
  • 29
  • 34
Ben
  • 16,124
  • 22
  • 77
  • 122
  • Why not to use `ContainerView` instead? – chrmod Jul 23 '13 at 09:04
  • From what I can tell you can't use ContainerView declaratively in the templates... is that right? – Ben Jul 23 '13 at 15:15
  • I found a work around using some jQuery. I define my stuff for the 2nd tab in a div, then use appendTo to move it over to the 2nd tab in the didInsertElement object... not pretty but it works – Ben Jul 23 '13 at 16:46
  • 1
    `ContainerView` is really an array of views and you can add views to it in imperative way if required. Check out http://emberjs.com/api/classes/Ember.ContainerView.html#sts=Ember.ContainerView%20Class%20packages/ember-views/lib/views/container_view.js:16 "Adding a view" section. The regular `pushObject` is appending new views. In your case you would like to nest a container view in another view to acts as its template. – chrmod Jul 23 '13 at 18:25
  • I answered a similar problem here. Let me know if its helpful: http://stackoverflow.com/questions/20841947/custom-components-with-multiple-yield-like-sections/21590775#21590775 – alalani Feb 06 '14 at 23:03
  • @ben have you found an answer for this? If so, I encourage you self-answer and to close this issue :) – Julian Leviston Apr 24 '14 at 09:52
  • @Ben I wonder if you would mind taking a look at this discussion over here: http://discuss.emberjs.com/t/handlebars-block-helper-based-on-templating-language-twig/5051/12 because it might be what you're looking for? Alternatively, I wonder if multiple outlets might be what you're after? http://stackoverflow.com/questions/14531956/multiple-outlets-in-ember-js-v2-router – Julian Leviston Apr 29 '14 at 03:17

3 Answers3

1

As of Ember 3.25 you can use so called "named blocks" (see the Passing multiple blocks subsection of https://api.emberjs.com/ember/release/modules/@glimmer%2Fcomponent).

Example component:

<h1>{{yield to="title"}}</h1>
{{yield}}

and then use it like this:

<PersonProfile @person={{this.currentUser}}>
  <:title>{{this.currentUser.name}}</:title>
  <:default>{{this.currentUser.siganture}}</:default>
</PersonProfile>
Andrey Stukalin
  • 5,328
  • 2
  • 31
  • 50
0

I think you should use named outlets for this

http://emberjs.com/guides/routing/rendering-a-template/

Julian Leviston
  • 1,646
  • 10
  • 21
0

Something like this should work:

layout.hbs

<div>
    <div class="header">Header Content</div>
    <div class="tab1">
        Tab 1 Controls.
        <input type="text" id="common1" />
        {{yield}}
    </div>
    <div class="tab2">
        Tab 2 Controls.
        <input type="text" id="common2" />
        {{view "view.secondView"}}
    </div>
</div>

app.js

App.MyDoubleDeckerView = Ember.View.extend({
    layoutName:"layout',
    templateName:"defaultTemplate", 
    secondView: Ember.view.extend({
        templateName: "defaultSecond"
    })
});

App.MyExtendedDoubleDecker = App.MyDoubleDeckerView({
    templateName:"myTemplate", 
    secondView: Ember.view.extend({
        templateName: "mySecondTemplate"
    });
});

In other words, invoke a view given by view.secondView from within your template. Then, set the secondView property in your class or subclass.

You could add a bit of syntactic sugar with

App.viewForTemplateName = function(templateName) {
    return Ember.View.extend({
        templateName: templateName
    });
};

Then, in your view definitions above, do

secondView: App.viewForTemplateName('mySecondTemplate')