Defining an HTML template to add using jQuery

I have an array that I iterate over. Every time the condition is true, I want to add a copy of the HTML below to the container element with some values.

Where can I put this HTML for reuse in an intelligent way?

 <a href="#" class="list-group-item"> <div class="image"> <img src="" /> </div> <p class="list-group-item-text"></p> </a> 

JQuery

 $('.search').keyup(function() { $('.list-items').html(null); $.each(items, function(index) { // APPENDING CODE HERE }); }); 
+68
json javascript jquery
Sep 07 '13 at 13:35
source share
6 answers

You can decide to use a template engine in your project, for example:

If you don't want to include another library, John Resig offers a jQuery solution similar to the one below.




Browsers and screen readers ignore unrecognized script types:

 <script id="hidden-template" type="text/x-custom-template"> <tr> <td>Foo</td> <td>Bar</td> <tr> </script> 

Using jQuery, adding template-based strings will resemble:

 var template = $('#hidden-template').html(); $('button.addRow').click(function() { $('#targetTable').append(template); }); 
+87
Sep 07 '13 at 13:59 on
source share

An old question, but since the question is “using jQuery”, I thought I would provide an option that would allow you to do this without introducing any vendor dependency.

Despite the fact that there are many templates in the world, many of their functions have recently become disillusioned with iteration ( <% for ), conventions ( <% if ) and transformations ( <%= myString | uppercase %> ), considered as a micro language in the best and anti-worst case patterns. Modern template methods simply encourage matching an object with its representation of the DOM (or other), for example. what we see with properties mapped to components in ReactJS (especially non-idle components).

Templates inside HTML

One property you can rely on to store HTML code for your template next to the rest of your HTML is to use an unused <script> type , for example. <script type="text/template"> . For your case:

 <script type="text/template" data-template="listitem"> <a href="${url}" class="list-group-item"> <table> <tr> <td><img src="${img}"></td> <td><p class="list-group-item-text">${title}</p></td> </tr> </table> </a> </script> 

When loading a document, read your template and mark it with a simple String#split

 var itemTpl = $('script[data-template="listitem"]').text().split(/\$\{(.+?)\}/g); 

Please note that with our token you get it in the variable format [text, property, text, property] . This allows us to nicely map it using Array#map with a display function:

 function render(props) { return function(tok, i) { return (i % 2) ? props[tok] : tok; }; } 

Where props might look like { url: 'http://foo.com', img: '/images/bar.png', title: 'Lorem Ipsum' } .

Putting it all together, if you have analyzed and loaded your itemTpl as described above, and you have an array of items in the scope:

 $('.search').keyup(function () { $('.list-items').append(items.map(function (item) { return itemTpl.map(render(item)).join(''); })); }); 

This approach is also just barely jQuery - you should use the same approach using vanilla javascript with document.querySelector and .innerHTML .

jsfiddle

Templates inside JS

The question you ask yourself is: do you want / need to define templates as HTML files? You can always build + reuse a template in the same way you would reuse most of the things you want to repeat: using a function.

In es7-land, using destructuring, pattern lines, and arrow functions, you can write completely beautiful component components that can be easily loaded using the $.fn.html method above.

 const Item = ({ url, img, title }) => ` <a href="${url}" class="list-group-item"> <div class="image"> <img src="${img}" /> </div> <p class="list-group-item-text">${title}</p> </a> `; 

Then you can easily display it, even displayed from an array, for example:

 $('.list-items').html([ { url: '/foo', img: 'foo.png', title: 'Foo item' }, { url: '/bar', img: 'bar.png', title: 'Bar item' }, ].map(Item).join('')); 

Oh and one final note: do not forget to sanitize your properties passed to the template if they are read from the database, or someone can pass HTML (and then run scripts, etc.) from their page.

+61
Aug 21 '16 at 14:12
source share

Add somewhere in the body

 <div class="hide"> <a href="#" class="list-group-item"> <table> <tr> <td><img src=""></td> <td><p class="list-group-item-text"></p></td> </tr> </table> </a> </div> 

then create css

 .hide { display: none; } 

and add in js

 $('#output').append( $('.hide').html() ); 
+10
Sep 07 '13 at 13:40
source share

Use an HTML template instead!

Since the accepted answer will be an overload of the script method, I would like to suggest another that, in my opinion, is much cleaner and safer due to the XSS risks associated with script overloading.

I made a demo to show you how to use it in action and how to insert one template into another, edit, and then add to the DOM document. https://codepen.io/DevWL/pen/YrjyWm?editors=1010

html example

 <template id="mytemplate"> <style> .image{ width: 100%; height: auto; } </style> <a href="#" class="list-group-item"> <div class="image"> <img src="" /> </div> <p class="list-group-item-text"></p> </a> </template> 

js example

 // select var t = document.querySelector('#mytemplate'); // set t.content.querySelector('img').src = 'demo.png'; t.content.querySelector('p').textContent= 'demo text'; // add to document DOM var clone = document.importNode(t.content, true); // where true means deep copy document.body.appendChild(clone); 

HTML & lttemplate>

  • + Its contents are effectively inert until activated. Essentially, your markup is hidden by the DOM and does not display.

  • + Any content in the template will not have side effects. Scripts do not run, images do not load, sound does not play ... until a template is used.

  • + Content is not considered in the document. Using document.getElementById() or querySelector() on the main page will not return the child nodes of the template.

  • + Templates can be placed anywhere <head> , <body> or <frameset> and can contain any type of content that is allowed in these elements. Note that “anywhere” means that <template> can be safely used in places where the HTML parser is not allowed.

Return back

Browser support should not be a problem, but if you want to cover all the possibilities, you can easily check:

To find the <template> function, create a DOM element and verify that the .content property exists

 function supportsTemplate() { return 'content' in document.createElement('template'); } if (supportsTemplate()) { // Good to go! } else { // Use old templating techniques or libraries. } 

Some details on the script overload method

  • + Nothing is displayed - the browser does not display this block, since the <script> has display:none by default.
  • + Inert - the browser does not parse the contents of the script as JS, because its type has a value other than "text/javascript" .
  • - Security Issues - encourages the use of .innerHTML . Analyzing user data runtime can easily lead to XSS vulnerabilities.

Full article: https://www.html5rocks.com/en/tutorials/webcomponents/template/#toc-old

Useful link: https://developer.mozilla.org/en-US/docs/Web/API/Document/importNode http://caniuse.com/#feat=queryselector

+4
Oct 12 '17 at 1:10
source share

Another alternative: Pure

I use it and it helped me a lot. An example shown on their website:

HTML

 <div class="who"> </div> 

Json

 { "who": "Hello Wrrrld" } 

Result

 <div class="who"> Hello Wrrrld </div> 
+3
Sep 12 '14 at 20:45
source share

To solve this problem, I recognize two solutions:

  • The first comes with AJAX, with which you will have to download the template from another file and just add it every time you want with .clone() .

     $.get('url/to/template', function(data) { temp = data $('.search').keyup(function() { $('.list-items').html(null); $.each(items, function(index) { $(this).append(temp.clone()) }); }); }); 

    Note that an event must be added after ajax completes to make sure the data is available!

  • The second way is to directly add it to the original html, select it and hide it in jQuery:

     temp = $('.list_group_item').hide() 

    After adding a new instance of the template with

     $('.search').keyup(function() { $('.list-items').html(null); $.each(items, function(index) { $(this).append(temp.clone()) }); }); 
  • Like the previous one, but if you do not want the template to stay there, but only in javascript, I think you can use (did not check it!) .detach() instead of hiding it.

     temp = $('.list_group_item').detach() 

    .detach() removes elements from the DOM, keeping data and events alive (.remove () doesn't work!).

+2
Sep 07 '13 at 13:41
source share



All Articles