Jeanluca Scaljeri
Jeanluca Scaljeri

Reputation: 29129

EmberJs: render a template within a handlebars-helper into its parent element

Because I have the name of a View inside a variable I'm using a handlebars helper to get it rendered.

So, I have an object as follows (all simplified of course)

config = Ember.Object.create({ view: "MyTplView"}) ;

Next, I have the following template

<script type="text/x-handlebars" data-template-name="index">
    <div id="container">
        {{helperViewRenderer config}}
    </div>
</script>

And the Handlebars helper

Ember.Handlebars.registerBoundHelper('helperViewRenderer', function(value, options) {
    var template = App[value.view].create() ;
    template.appendTo("#container") ;
}) ;

The problem is that I try to insert the template into the element with id "container", which doesn't exist at that moment. What are the possibilities to fix this. For example, is it possible to get a HTML-string from the template and return this instead ?

Upvotes: 1

Views: 1098

Answers (2)

James A. Rosen
James A. Rosen

Reputation: 65242

I have occasionally found it valuable to define a child view class inside of a parent view class instead of as a global. You can pass any path -- global or local -- to the view helper, and the current view is available as view in the current context. Thus,

App.ParentView = Ember.View.extend({
  template: Ember.Handlebars.compile("The parent's child: {{view view.ChildView}}."),

  ChildView: Ember.View.extend({
    template: Ember.Handlebars.compile("-- child view --")
  })
});

Upvotes: 2

DF_
DF_

Reputation: 3973

Ember tries to go the route of creating 'outlets' through the use of the new router.

If you want to use the appendTo method then obviously you have to append your template to an existing HTML element. In that way, you can't get a HTML string from a template (unless you know it is part of a parent template). However if you're not too bothered about where you're inserting your template, then you can use a straight append which will add the template to the end of the body.

I think in your case it would be better to get familiar with the router, as you seem to be wanting to render different templates inside the same main template. Therefore you can easily separate these out by using the URL as a variable, and injecting the relevant view into the outlet.

App.Router.map(function () {
  this.route("index", { path: "/" });
  this.route("first", { path: "/view1" });
  this.route("another", { path: "/view2" });
});

App.FirstRoute = Em.Route.extend({
  renderTemplate: function () {
    this.render('view1', { outlet: 'main' });
  }
});

App.AnotherRoute = Em.Route.extend({
  renderTemplate: function () {
    this.render('view2', { outlet: 'main' });
  }
});

View:

<script type="text/x-handlebars" data-template-name="index">
    <div id="container">
        {{outlet main}}
    </div>
</script>

This way you don't need any handlebars helper passing in variables and it's all neatly wrapped up in Ember conventions.

Upvotes: 1

Related Questions