53

I am struggling to find a clean solution to my problem and was wondering if anyone could offer some tips.

I have "templates.html" which contains a collection of HTML snippets which I want to load into JavaScript and use. What is a good way to access the templates/snippets bearing in mind that templates.html is not a loaded DOM document?

I was thinking about using document.open to create a DOM to access but I think this has issues on certain browsers.

2
  • 8
    SMH - it's embarrassing how many people gave jQuery answers and not Javascript ones. Commented May 10, 2019 at 11:02
  • A lot changed since 2011, so these present days, maybe you want look: stackoverflow.com/a/58862506/890357 Commented Nov 14, 2019 at 17:29

7 Answers 7

45

Use jQuery and the .load() ( http://api.jquery.com/load/ ) method to inject the loaded document into the DOM.

$(function() {
    $('#content').load('/templates.html');
});
Sign up to request clarification or add additional context in comments.

1 Comment

This was the solution for me, just don't forget to add the callback function! because if you are going to add functionality maybe the content is not loaded yet, so better to wait for it. $('#content').load('/templates.html', function () { // Things to do when the html is loaded });
35

This is a bit old but since "Load HTML template with JavaScript" nowadays should refer to the loading of a HTMLTemplateElement here is a more modern looking approach to loading natives templates with javascript that also works for your use case.

First of all using <template> is already better than loading HTML into a hidden DIV because templates are innert and don't display content. You can have the templates being rendered from the beginning and use them whenever you need.

<html>
<head>
  <template>My template</template>
</head>
<body>
  <script>
  document.body.append(
    document.importNode(
      document.querySelector('template').content,
      true
    )
  )
  </script>
</body>
</html>

Or create them dynamically.

const template = document.createElement('template')
// modify the template's content
template.content.append(document.createElement('div'))
// add it to the document so it is parsed and ready to be used
document.head.append(template)

Because we want the content of the template to be built based on some text we get from the network, we have to parse it and add it to our template.content.

const text = fetchTemplateSomehowAsText('my-template.html')
const parsedDocument = new DOMParser().parseFromString(text, 'text/html')
template.content.append(parsedDocument.querySelector('#my-snippet'))

If my-template.html already comes wrapped in the <template> tag we can avoid the part of creating the template element manually because the DOMParser already creates the template element for us.

document.head.append(
  new DOMParser().parseFromString(text, 'text/html')
    .querySelector('template')
  )
)

This is a snippet I've been using to load templates into the document dynamically that uses what I just explained.

Comments

25

You can load the html into a hidden div and then you will have a DOM access the easiest way to load the html to a DIV is using jquery load: http://api.jquery.com/load/

$( "#result" ).load( "ajax/test.html" );

4 Comments

Some example code is always nice. That's why I prefer peterp's answer
I'm trying to incorporate this method in my Flask app but the html file does not load. I'd really appreciate any input! stackoverflow.com/questions/55735664/…
@Felipe the answer is from 2011 you you can use it or not but you don't need to downvote
@kleinohad jQuery has been replaced by native functions, which makes the answer outdated. IMO it should no longer be the accepted answer for a question that says "load HTML template with JavaScript"
10

another way to do this is using requireJS.

require (['text!template_name'], function(yourTemplate) {
  // do stuff in here with yourTemplate dinamically load
}

2 Comments

Hi Andrei, Thanks for the answer, I have not really used requirejs but was aware of it, now I have a reason to tinker.. bennadel.com/blog/…
you can dynamically load a lot of stuff with it, it's very usefull. I use it for coffeescript code and templates.
7

For simple requiring you can try:

var xhr = new XMLHttpRequest(); 
xhr.onreadystatechange = function () {
    if (xhr.readyState === 4) {     
        //do something with xhr.responseText
    }   
};      
xhr.open('GET', '/template.html');
xhr.send();  

Comments

4

you could load the template async using jquery ajax

$.get("/html/template01.html")
.done((data) => {
    console.info(data); // output the content of the html file
});

1 Comment

Is it possible to connect that template "template01.html" to a controller (defined in controller.js (Ionic/Cordova app)) without a state?
-1

EDIT NOTE: if you are using ES6 go the 3rd edit directly

What about reading the files which contains your HTML templates after loading the page and load them in sessionStorage or localStorage as string value under appropriate names ?

Then you can just access your template in javascript by using the name or key specified for that template on sessionStorage or localStorage depending on which you choose.

(instead of using sessionStorage or localStorage you could preserve their stockage capabilities by designing an object used in global scope that will allow you to store templates and serve them on demand )

This is just theoretic I haven't tried it yet but one of the advantages I can see for this method is that you will not have your template code displayed in the page source.

Edit:

Going practical we can achieve this like the following.

Using fetch instead of jQuery you will have something like this :

var fileURL = "URL of the file to load";

fetch(`${fileURL}`).then(function(response) {
        response.text().then(function(text) {
                console.log(text); // output the file content as text
                // put data in localStorage or sessionStorage here
                localStorage.setItem("my-template", text);
        })
});

Now if you want your code to be executed only when localStorage["my-template"] exists do it that way:

if (localStorage["my-template"]) {
        console.log("'my-template' exist");
        // here you put the code that needs "my-template"
} else {
        console.log("error: could not find 'my-template'");
}

Now you can access "my-template" anywhere from javascript using :

localStorage.getItem("my-template");

Note that if you want to avoid errors the generation of your custom elements that use "my-template" should be done inside:

if (localStorage["my-template"]) { ... }

Also some minors changes may be required prior to data usage probably a simple text formatting operation. As the data-string contained in localStorage appears to contains text formatting characters. When applying the text as innerHTML for any element in the page it behaves correctly despite the text formatting chars it contains.

Given the fact that you will only get the content of your file when the response is resolved.

You can start the processing related to that file by :

  • sending an event that you will attach to a function for processing
  • calling a function that will perform the processing directly

Those needs to be done or initiated inside this part of the fetch instruction :

response.text().then(function(text) { ... })

EDIT 2:

If you do not want to put your templates code in the page you will need to remove the <template> tags that encapsulate them and add the resulting code as the innerHTML of the shadow DOM on the customElements that require the templates.

Here is a short example :

class TestCustomElement extends HTMLElement {
    
    constructor() {
        super(); // always call first !!

        // create and attach a new shadow DOM to the element
        this.shadow = this.attachShadow({mode:"open"});  
        
        // we define the apparence of our customElement by setting it's shadow DOM innerHTML property
        this.shadow.innerHTML = `<style> 
            .container {
                width:fit-content;
                color:black;
                background-color: yellow;
                border: 1px solid red;
                padding:5px;
            }
            
            span {
                padding:0px 10px 0px 10px;
            }
        </style>
        
        <div class="container">
            <span>"Hi I'm a test span !"</span>
        </div>`; 

       // here you put the functionalities  
    }
    
    // here you put the callbacks
}

customElements.define("test-custom-el", TestCustomElement); 

If you want to try this there is this codepen or you can save the above code as a .js file. Then you can load that file into the header of your test page by using this:

<script src="FileName.js" defer></script>

To add one customElement of that class just add those tags in the body of your test page :

<test-custom-el></test-custom-el>

Now if you want to combine this with the fetch example of this post you will have to remove the <template> tags from your templates files and set the loaded content as the value for the innerHTML of the shadow DOM for the customElements that will use them.

This way there's no need to add <template> code into your page.

Edit 3 :

BEST WAY USING ES6 :
After some more tests I figured it out that the best way to import an .html file in a .js file using ES6 is to include a .js file instead of a .html one this way it allows the use of the import / export functionalities pretty easily without having to deal with some more heavy async operations that are required to retrieve an html file in a javascript ES6 file.

Here is a short example on how to perform that :
for this example we assume that you have a "template.html" file in the same directory as a "module.js" file.

First You need to create a "template.js" file from "template.html" in which you put the following :

export default `Put the content of template.html here`;

You can create a little script to create those files for you.

When you have this "template.js" file you can now import it in your "module.js" file by simply using this import statement:

import template from './template.js';

Then you can use it to assign the template value of your module in it's constructor this way :

this.template = new DOMParser().parseFromString(template, 'text/html').querySelector('template');

this.template will now contain a <template> element as described in the "template.js" file (the element is created by the DOMParser).

In short your "module.js" file should look like this :

import template from './template.js';

export default class MyModule extends HTMLElement {

        constructor() {
            super();
            this.shadow = this.attachShadow({mode:"open"});
            this.template = new DOMParser().parseFromString(template, 'text/html').querySelector('template');
            this.shadow.appendChild(this.template.content);
        }
}

1 Comment

As it's written, this answer is difficult to read. Please remove any outdated information when updating the answer. If the new information is self-contained, consider submitting it as a separate answer instead.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.