Re-render compiled Ember templates

How can I re-compile ember handlebars templates? Example: I have a url /page/:page_id which returns json object. This object describes the page structure. Each page has different structure.

{page: {
    id:2, 
    structure:[
        {type: 'row', children:[...]}, 
        {type: 'module', id: 42}
   ]
}

I have to dynamically change the template content according to the json object.

{{#row}}
    {{#container}}
        Inner text
    {{/container}}
{{/row}}
{{#module id=42}}

And recompile it

Ember.TEMPLATES['page'] = Ember.Handlebars.compile(hbs)

It works only for the first time. So overwriting page property in TEMPLATES doesn’t affect.

In order to do what you’re asking, you would create a view class and update the template property on the view. (Though, this means that you’re compiling templates in the browser…are you sure you want to do this?)

An example (supposing this is the PageDetail route):

App.PageDetailView = Ember.View.extend({
  template: Ember.Handlebars.compile(hbs),
  updateTemplate: function() {
    // Logic for creating a new template 
    this.set('template', Ember.Handelbars.compile(newHbs));
  },
  controllerModelDidChange: function() {
    Em.run.once(this, 'updateTemplate');
  }.observes('controller.model')
});

You can also manually the DOM with the View object using appendChild and removeFromParent, etc, that way you’re not having to build a string template that then gets compiled. Not sure what the performance tradeoffs there would be.

That being said, the way things have been going with Ember you might be better suited in building Helpers and Components that handle every possibility for the page structures. So, you might get something like:

{{#each structure}}
  {{render-structure type=type}}
{{/each}}

I thought about helpers and components. How to be in case with children

{{#each structure}}
    {{render-structure type=type}}
{{/each}}

What should be in render-structure compoent view code to render child in deep?

So, the render-structure component could perhaps be recursive…

// PageDetail.hbs
{{#each item in structure}}
    {{render-structure type=item.type data=item}}
{{/each}}

// components/renderStructure.hbs
{{...Other template content...}}
{{#each child in data.children}}
  {{render-structure type=child.type data=child}}
{{/each}}
1 Like

Thanks you very much!

I can’t find a way how to wrap children with element. Block - none, container - div, h2 - h2, module - component

"structure": [
    {
        "type": "block",
        "name": "departments",
        "children": [
            {
               "type": "container",
                   "children": [
                       {
                           "type": "h2",
                           "innerHtml": "Contact us today"
                       },
                       {
                          "type": "module",
                          "name": "ContactDepartment",
                          "theme": "responsive1",
                          "id": 1
                       },
                 ]
             }
         ]
    }
]

I should get something like

{{#h2}}
    {{innerHtml}}
    {{#if data.children}}
        {{#each child in data.children}}
            {{render-structure type=child.type data=child}}
        {{/each}}
    {{/if}}
{{/h2}}

or

{{#module id=id theme=theme name=name}}
    {{#if data.children}}
        {{#each child in data.children}}
           {{render-structure type=child.type data=child}}
        {{/each}}
    {{/if}}
{{/module}}