1

I am writing an application that uses handlebars.js but The example code on their website uses JQuery so as do many other online resources. However, I want to simply compile and render a handlebars template using vanilla js.

This is the HTML template

<script id="entry-template" type="text/x-handlebars-template">
  <div class="entry">
    <h1>{{title}}</h1>
    <div class="body">
     {{body}}
    </div>
  </div>
</script>

The JS I have for the compilation is below, as suggested in the answer to a similar question here Does Handlebars require jQuery

var source = document.getElementById('entry-template').innerHTML;
var template = Handlebars.compile(source);

Assume my JSON is stored in a variable called myData.

When it comes to rendering the template with JQuery you can simply do

$('#data-section').append(template(myData));

But I want to use vanilla JS so I'm doing this:

var compiledHTML = template(myData);    
var dataContainer = document.getElementById('data-section');
dataContainer.appendChild(compiledHTML);

but I get the error

Uncaught TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.

How do I get this to work?

3 Answers 3

3

You can use the Element.insertAdjacentHTML method which is cross browser friendly.
See docs here: https://developer.mozilla.org/en-US/docs/Web/API/Element/insertAdjacentHTML

There are four options for how to insert the compiled template into the DOM:

  1. beforebegin (before opening tag or as a previous sibling)
  2. afterbegin (first child)
  3. beforeend (last child)
  4. afterend (after closing tag or next sibling)

In my case I was attaching a template to the end of the body tag so it looked like so document.getElementsByTagName('body')[0].insertAdjacentHTML("beforeend", myHbsTemplate(VM));

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks Andre. insertAdjacentHTML is definitely very useful. The issue I was having was due to me confusing Element objects with nodes i.e. developer.mozilla.org/en/docs/Web/API/Node & developer.mozilla.org/en-US/docs/Web/API/Element
Thanks for the answer, works for me! For the future reference: use "document.body" instead of "document.getElementsByTagName('body')[0]".
2

The output of calling a compiled template is a string, and not a DOM tree. You might want to use innerHTML instead.

dataContainer.innerHTML = compiledHTML;

2 Comments

That works perfectly. Does this work because there is some type conversion occurring behind the scenes?
0

The issue seems to be with the fact that the variable compiledHTML is a string. The solution I have gone with is to use DOMparser, which allows me to convert the sting to a DOM node that I can then pass into appendChild.

The code I'm using is this

var parser = new DOMParser();
var convertedHtml = parser.parseFromString(compiledHTML, 'text/xml');
dataContainer.appendChild(convertedHtml.documentElement);

I had to use documentElement because the HTML which results from the parse generates a HierarchyRequestError error.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.