donderdag 8 maart 2018

How to use html5 <template> with jQuery

So you have decided to go full html5 in your website. Congrats, welcome to 2018 where Internet Explorer is closer to death.


 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
<!-- Learn about this code on MDN: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/template -->

<table id="producttable">
  <thead>
    <tr>
      <td>UPC_Code</td>
      <td>Product_Name</td>
    </tr>
  </thead>
  <tbody>
    <!-- existing data could optionally be included here -->
  </tbody>
</table>

<template id="productrow">
  <tr>
    <td class="record"></td>
    <td></td>
  </tr>
</template> 


Now if you wish to use template, but don't wish to use the code that's shown on MDN because you are more comfortable with jquery, you only need this one sentence to get the template into a jQuery object you can manipulate and later append to your favorite node.

The full sample for createing, modifying and appending a node from a template.


1
2
3
4
$content = $(document.importNode($('template#productrow').prop('content'), true));
$content.find('td.record').text('foo');
$content.find('td:not(.record)').text('bar');
$('#producttable thead').append($content);

You can fiddle with it here: https://jsfiddle.net/Ld9421o1/

Now a little breakdown of what does what

This is the entire line needed to turn a template into a jquery object you can manipulate.

1
var $content = $(document.importNode($('template#productrow').prop('content'), true));
Below the breakdown of the individual components

This searches a <template> element with the id attribute with the value productrow.
Then it accesses the property 'content' on that object.

1
$('template#productrow').prop('content')
An alternative could be

1
2
$('template#productrow').get(0).content;
$('template#productrow')[0].content;
The document-fragment you have now is not attached to the window.document object. It's free floating without parents. This also means you can't append it to any node you have on your document.

This is why you call this code. What it does is clone the fragment you have supplied(that's what the true is for) setting window.document to the documents fragment parent, but it's still not attached to any DOM element you have in your body. It is as if you called $('selector').detach() on an element.
And then it returns the cloned node to you.
1
document.importNode(documentFragment, true)

Now we wrap the clone in jQuery so we have a nice manipulatable object we can change without changing the template around and because it's still detached from the DOM, these manipulations will happen really fast because there's no re-rendering of the page involved.

1
$(document.importNode(documentFragment, true))