Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Defining a HTML template to append using JQuery

People also ask

How do you add a HTML template?

You can use the <template> tag if you have some HTML code you want to use over and over again, but not until you ask for it. To do this without the <template> tag, you have to create the HTML code with JavaScript to prevent the browser from rendering the code.

What is difference between append and HTML in jQuery?

html() will completely replace the content inside the tag that the selector corresponds to. $('#'). append() will just append to the end of the content inside the tag.

What is append in jQuery?

jQuery append() Method The append() method inserts specified content at the end of the selected elements. Tip: To insert content at the beginning of the selected elements, use the prepend() method.

HOW include HTML in jQuery?

Step 1: Firstly, we have to open that Html file in which we want to add the jQuery using CDN. Step 2: After then, we have to place the cursor between the head tag just before the title tag. And, then we have to use the <script> tag, which specify the src attribute for adding.


Old question, but since the question asks "using jQuery", I thought I'd provide an option that lets you do this without introducing any vendor dependency.

While there are a lot of templating engines out there, many of their features have fallen in to disfavour recently, with iteration (<% for), conditionals (<% if) and transforms (<%= myString | uppercase %>) seen as microlanguage at best, and anti-patterns at worst. Modern templating practices encourage simply mapping an object to its DOM (or other) representation, e.g. what we see with properties mapped to components in ReactJS (especially stateless components).

Templates Inside HTML

One property you can rely on for keeping the HTML for your template next to the rest of your HTML, is by using a non-executing <script> type, e.g. <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>

On document load, read your template and tokenize it using a simple String#split

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

Notice that with our token, you get it in the alternating [text, property, text, property] format. This lets us nicely map it using an Array#map, with a mapping function:

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

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

Putting it all together assuming you've parsed and loaded your itemTpl as above, and you have an items array in-scope:

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

This approach is also only just barely jQuery - you should be able to take the same approach using vanilla javascript with document.querySelector and .innerHTML.

jsfiddle

Templates inside JS

A question to ask yourself is: do you really want/need to define templates as HTML files? You can always componentize + re-use a template the same way you'd re-use most things you want to repeat: with a function.

In es7-land, using destructuring, template strings, and arrow-functions, you can write downright pretty looking component functions 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 could easily render it, even mapped from an array, like so:

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

Oh and final note: don't forget to sanitize your properties passed to a template, if they're read from a DB, or someone could pass in HTML (and then run scripts, etc.) from your page.


You could decide to make use of a templating engine in your project, such as:

  • mustache
  • underscore.js
  • handlebars

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 rows based on the template would resemble:

var template = $('#hidden-template').html();

$('button.addRow').click(function() {
    $('#targetTable').append(template);
});

Use HTML template instead!

Since the accepted answer would represent overloading script method, I would like to suggest another which is, in my opinion, much cleaner and more secure due to XSS risks which come with overloading scripts.

I made a demo to show you how to use it in an action and how to inject one template into another, edit and then add to the document DOM.

example html

<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>

example js

// 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&gt

  • +Its content is effectively inert until activated. Essentially, your markup is hidden DOM and does not render.

  • +Any content within a template won't have side effects. Scripts don't run, images don't load, audio doesn't play ...until the template is used.

  • +Content is considered not to be in the document. Using document.getElementById() or querySelector() in the main page won't return child nodes of a template.

  • +Templates can be placed anywhere inside of <head>, <body>, or <frameset> and can contain any type of content which is allowed in those elements. Note that "anywhere" means that <template> can safely be used in places that the HTML parser disallows.

Fall back

Browser support should not be an issue but if you want to cover all possibilities you can make an easy check:

To feature detect <template>, create the DOM element and check 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 insights about Overloading script method

  • +Nothing is rendered - the browser doesn't render this block because the <script> tag has display:none by default.
  • +Inert - the browser doesn't parse the script content as JS because its type is set to something other than "text/javascript".
  • -Security issues - encourages the use of .innerHTML. Run-time string parsing of user-supplied data can easily lead to XSS vulnerabilities.

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

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

CREATING WEB COMPONENTS Creating custom web components tutorial using HTML templates by Trawersy Media: https://youtu.be/PCWaFLy3VUo


Add somewhere in 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 to your js

$('#output').append( $('.hide').html() );