Is it possible to somehow take a DOM element from a underscore template and use it as another template?
The idea is that my app needs to render a document that contains
I know I'm 3 years late to the conversation, but none of these answers applied at all to a situation I had in my latest project. And since the way I was originally thinking of doing this ended up working, I figured I should post it in case anyone else wants to actually nest underscore.js templates, as the title of this question states.
My requirements were basically:
1) If there are dynamic pieces in a template, they should be able to re-render themselves individually--without requiring that the entire template be re-rendered with the updated data.
2) Dynamic pieces shouldn't need to be splintered off into their own templates on the same level as the parent template; rather, there should be a sort of template hierarchy--a template declaring all the sub-templates required for itself.
The concept of nested templates in Underscore.js is the same as in PHP (for example). The following code is an example of "echoing PHP":
'; ?>
While this nested syntax can get super convoluted and confusing, the idea is simple:
Echo code that will echo values later.
This applies in Underscore.js templates as well.
The code will look like this:
" %>
Let's break this down a little bit. The line with the first NOTE
is our key line here. Normally when Underscore compiles this template, you would expect the value of value
to be printed in both the outer and inner templates. We did a few things to prevent this from happening:
1) Turn the nested underscore statement into a string.
2) Interpolate that string (
<%= "string here" %>
).3) Escape the closing
>
in the nested underscore statement (\>
). This prevents Underscore's regex from matching this with the opening tag from step 2 (<%=
). When this string is echoed, the escape character will be removed, leaving%>
, ready to be interpreted by Underscore on the next pass.
Doing this same thing in the second NOTE
in our example prevents the browser from ending the first script
tag. Nested script
tags technically aren't allowed, so the browser looks for the first sequence of characters: and then ends script execution. This stops the browser from recognizing this sequence.
For a more in-depth example, see this JSFiddle.
I don't endorse this as anywhere near the best way to do this sort of thing. It is, after all, very hacky. While @John z's answer breaks my first requirement, which wasn't an option for me, the other option of splintering off dynamic pieces in a template into their own templates may be easier to deal with. It's just less organized.
The location of all these nested script
tags in your DOM can get hard to keep track of (as the nested script
tags will get injected dynamically into the DOM when and wherever you insert the outer template). The risk of duplication is high, and can be annoying to maintain.
The difficulty of nesting templates increases drastically for each level of nesting (to nest a template in a nested template, you'd have to escape everything again, etc...). The fiddle includes an example of this.