Search code examples
javascripthtmltemplatestemplatingclient-side-templating

Templating HTML with hidden state instead of comment or custom script tag


Javascript best practices & conventions, such as those emphasized by John Resig and by Nicholas Zachas, author of book Maintainable JavaScript, suggest using HTML comments or script tags with a custom type to store HTML templates.

Comment example:

<div id="myTemplate">
<!-- <ul><li>$item</li></ul> -->
</div>
<script>
   var myTemplate = document.getElementById('myTemplate').childNodes[0].data;
   var myHtml = myTemplate.replace(/\$item/g, itemValue);
</script>

Script tag example:

<script id="myTemplate" type="text/x-html-template">
    <ul><li>$item</li></ul>
</script>
<script>
   var myTemplate = document.getElementById('myTemplate').innerHTML;
   var myHtml = myTemplate.replace(/\$item/g, itemValue);
</script>

I strongly dislike the comment-based templating because comments are supposed to be just that--comments, intended to be ignored by the functioning application--and as such I'm a little bewildered as to how it even gets to be suggested by JS gurus.

The script tag templating makes a lot more sense, and I'd normally call it a best if not wonderful practice because the purpose and initial non-function are well-delineated. My only issue is that in some modern editors the color highlighting, autocompletion, auto markup validation, etc., are all lost while working within the script tag.

An approach to templating I've taken in the past is to put it all in a container div, then classify the container div as class="template", then in CSS mark it as ".template { display: none; }".

<div id="myTemplate" class="template">
    <ul><li>$item</li></ul>
</div>
<script>
   var myTemplate = document.getElementById('myTemplate').innerHTML;
   var myHtml = myTemplate.replace(/\$item/g, itemValue);
</script>

This has worked fine for me, although the DOM parser and renderer obviously processes the data up front unnecessarily, but I'm not sure whether this is really all that big of an issue or not, as long as the templating constructs do not break HTML validity rules.

My question, then, is, what am I missing? Is the only reason why this third approach to storing template markup--that is, putting it in the DOM as display:none--is discouraged because the DOM parser and renderer will process it anyway? Or are there other reasons, perhaps technical, that I haven't come across yet? I'd like to know because, again, I want to take advantage of my editor's ability to help me fine tune a proper HTML template.


Solution

  • I think that the best method is using the <script> tag. But for your editor, it must has a solution to add HTML support into the <script> tag with type="html/template-something" too.

    For example I code in Sublime Text, and when I want to write a script template tag, my editor showed me something like this:

    enter image description here

    As you see, the h1 tag inside the script tag, is different from real h1 in my HTML. So I search on the internet, and find a solution: finding a file name called HTML.tmLanguage and make this changes:

    // change this line
    <string>(?:^\s+)?(&lt;)((?i:script))\b(?![^&gt;]*/&gt;)</string>
    
    // to this line
    <string>(?:^\s+)?(&lt;)((?i:script))\b(?!([^&gt;]*text/template[^&gt;]*|[^&gt;]*/>))</string>
    

    And after that, I get this result in my editor:

    enter image description here

    I'm sure there must be a solution for your editor.


    Visual Studio 2012

    In Visual Studio 2012, if you use the script like this:

    <script id="myTemplate" type="text/html">
    

    it will parse the content within it as HTML.


    display: none;

    Your last solutions, using display: none isn't good, because Search Engines will index the content within it, see this: