Why should we wrap our templates inside script blocks?
Asked Answered
B

2

8

Background

All the JS template engines recommend putting your template text inside script blocks like so:

<script id="peopleTemplate" type="text/template">
   {#people}
   <div class="person">Name: {firstName} {lastName}</div>
   {/people}
</script>

but many developers (understandably) dislike this because they lose HTML syntax highlighting in their code editor inside the script block. I've seen the workarounds like this: Keep correct HTML syntax highlighting in <script> "text/html" templates . This question is not asking about workarounds.

I know one danger is that web browsers will attempt to fix invalid HTML so calling $('#peopleTemplate').html() will have unpredictable results. However, off the top of my head, I cannot think of any examples to illustrate this.

Question

What are some of the other dangers of replacing the script tag with a div ?

Bonus: can someone come up with a good fiddle that illustrates the browser HTML auto-fixing?

Brill answered 13/3, 2013 at 13:9 Comment(6)
For Dust, it is recommended that the templates be placed in separate files, not in script tags within an HTML file. Syntax highlighting for Vim (github.com/jimmyhchan/dustjs.vim) and Textmate (github.com/jimmyhchan/Dustjs.tmbundle) are available.Selfinterest
Dust doesn't really recommend external templates, akdubya (author of dust) describes it as "Storage agnostic" meaning it doesn't care how you load your templates. LinkedIn, who is actively developing their own Dust branch, promotes external templates because it allows them to load templates via CDN. But you're right, a template stored in a .html file will have HTML syntax highlighting in most code editors. But my question is really about why are internal templates recommended to be stored in script blocks, and not a div?Brill
A template which is a single <li> is invalid HTML, the browser is free to wrap it in a <ul> to correct it. A template can contain multiple id="{{id}}" attributes which will be valid when filled in but are invalid HTML until then. Not lying to the browser is an easy way to future-proof your code; just because something invalid doesn't break today doesn't mean it won't break in the next point release.Aquanaut
@WalterStabosz - akdubya makes it possible to load templates however you please. However, he recommends that you precompile templates: "Precompilation is the recommended approach for general use." As such, storing templates in script tags is not the recommended approach.Selfinterest
@Selfinterest good point. So what is your workflow ? Write the templates in external HTML files that get dust compiled as part of your build script?Brill
@WalterStabosz that's basically it. You can add a watcher to your directory to compile on save, or you can compile on page refresh (in dev only). One thing to remember is to always include your compiled templates: <script type="text/javascript" src="template.js"></script>.Selfinterest
C
9

Here's an example of the browser auto-fixing issue: http://jsfiddle.net/KPasF/

The template is:

<table>
    <tr>
        {{#numbers}} <th> {{.}} </th> {{/numbers}}
    </tr>
</table>

The data is:

var json = { "numbers": [ 1, 2, 3 ] };

See the fiddle http://jsfiddle.net/KPasF/ for the different results when the template is in a hidden div, and then again in a script block.

Explanation

When you put this in a hidden <div>, the browser will strip the content outside the <th> tags (the {{#numbers}} and {{#numbers}} mustache tags). Which just leaves the {{.}}, which will bind to the json object and render as [object Object]

Putting the template in a <script type='text/html'> block works as you would expect, we get three <th>'s

Example of how browser mangles a template if housed inside a <div> instead of a <script>:

enter image description here

Compulsion answered 15/3, 2013 at 12:21 Comment(2)
Thanks for simple the example. I added a screenshot of how Chrome interpreted the two templates. It clearly shows the importance of using <script> vs <div>.Brill
Nice, I was just creating a similar example with table markup. This demonstrates the issue quite well.Jejunum
B
1

Another example, if you have the following inline template (wrapped in a div):

<div id="template">
   {#Users}
       <a href="/ViewUser?ID={UserID}">{UserName}</a>
   {/Users}
</div>

And then you use jQuery.html() to grab the template text, you will get different results depending on the browser. Firefox is the most mangled as it escapes the brackets inside the href.

Chrome 26.0.1410.64:

{#Users}
     <a href="/ViewUser?ID={UserID}">{UserName}</a>
{/Users}

Firefox 10.0.1:

{#Users} 
    <a href="/ViewUser?ID=%7BUserID%7D">{UserName}</a> 
{/Users}

IE 8.0.7601.17514:

{#Users} 
    <A href="/ViewUser?ID={UserID}">{UserName}</A> 
{/Users}
Brill answered 17/4, 2013 at 13:5 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.