Knockout's renderTemplateSource with nested anonymous templates

136 views
Skip to first unread message

Juan Cortines

unread,
Feb 14, 2014, 12:57:04 PM2/14/14
to knock...@googlegroups.com
Hi,

I'm trying to set a template engine based on Hogan.js like this:

engine.renderTemplateSource = function (templateSource, bindingContext, options) {
    // Precompile and cache the templates for efficiency
    var precompiled = templateSource['data']('precompiled');
    if (!precompiled) {
        precompiled = hogan.compile(templateSource.text());
        templateSource['data']('precompiled', precompiled);
    } 
    // Run the template and parse its output into an array of DOM elements
    return ko.utils.parseHtmlFragment(precompiled.render(bindingContext.$data.test, {}));
};

It works great when using all the time named templates.

The problems start if I mix named templates with anonymous templates. Example:

<!-- my "home" template -->

<div class="home container">
    <div>{{test}}</div>
    <div data-bind="template: {foreach: items}">
    <div>{{test}}</div>
    </div>
</div>

Both home and anonymous templates are binded to view models which expose a field called "test". The value on each of those two view models is different.

The problem is that when processing the parent template, home, both {{test}} tags are evaluated and replaced with the value from the home view model.

Any ideas as to how to avoid this and get each {{test}} flag evaluated in its own bindingContext?

Thanks!

Juan Cortines

unread,
Feb 14, 2014, 1:11:57 PM2/14/14
to knock...@googlegroups.com
By the way.. some will say use turn "test" into an observable :)

Well, the thing is that we need to localize many labels and declaring observables for all of them seems to be an "overkill"

That's why we use the template context and tags evaluated when templates are rendered.

Thanks

Michael Best

unread,
Feb 14, 2014, 3:32:31 PM2/14/14
to knock...@googlegroups.com
The {{test}} values are replaced by the template engine before the bindings are evaluated. You could split up to the template, or use a looping technique that's part of the template engine, or use a Knockout data-bind for the inner value.

Here's the latter:

<div class="home container">
    <div>{{test}}</div>
    <div data-bind="template: {foreach: items}">
    <div data-bind="text: test"></div>
    </div>
</div>

-- Michael

Juan Cortines

unread,
Feb 14, 2014, 5:15:00 PM2/14/14
to knock...@googlegroups.com
Thanks Michael, it's interesting. Maybe the solution is to use data-bind, as you advised, or Knockout.Punches, to keep Mustache's curly braces convention, and then go back to Knockout's native template engine..

I understand that using data-bind over non-observable view model field should not add much overhead. Is that correct? (excuse me if that's a silly question)

Thanks!
Reply all
Reply to author
Forward
0 new messages