rjbultitude
rjbultitude

Reputation: 935

Compiling and rendering handlebars template with vanilla JS

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?

Upvotes: 1

Views: 3675

Answers (3)

a_dreb
a_dreb

Reputation: 189

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

Upvotes: 3

rjbultitude
rjbultitude

Reputation: 935

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.

Upvotes: 0

Joseph
Joseph

Reputation: 119877

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;

Upvotes: 2

Related Questions