Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to use HTML <template> with variables (with Vanilla JS)

Currently I'm doing the following:

This is my HTML template

<template id="catDisplayTemplate">
      <div class="col">
        <img class="mehow" src="{{catImg}}" alt="" data-name="{{catName}}" data-id="{{catId}}">
        <div class="row space-between">
          <div class="col">
            <p class="description">{{catDescription}}</p>
          </div>
       </div>
       </div>
</template>

The following code change the moustaches but it feels like repeating itself

const catTemplate = document.querySelector('#catDisplayTemplate').innerHTML;
catTemplate = catTemplate.replace(/{{catImg}}/g, catData.img);
catTemplate = catTemplate.replace(/{{catName}}/g, catData.name);
catTemplate = catTemplate.replace(/{{catId}}/g, catData.id);
catTemplate = catTemplate.replace(/{{catDescription}}/g, catData.description);

*catData is the object with the details.

Is there a better/other way?

like image 707
DaffyDuck Avatar asked Oct 25 '25 05:10

DaffyDuck


1 Answers

You could write an interpolate function that accepts the template and an object containing the keys and values you want to replace. There are several examples in the answer to this question: Can ES6 template literals be substituted at runtime (or reused)?

Here is one that I use, which I borrowed from here: It sanitizes input against XSS attack and replaces placeholders with variables. I am likely to split this into separate functions for production use.

interpolate(template, params) {
    const replaceTags = { '&': '&amp;', '<': '&lt;', '>': '&gt;', '(': '%28', ')': '%29' };
    const safeInnerHTML = text => text.toString().replace(/[&<>\(\)]/g, tag => replaceTags[tag] || tag);
    const keys = Object.keys(params);
    const keyVals = Object.values(params).map(safeInnerHTML);
    return new Function(...keys, `return \`${template}\``)(...keyVals);
 }

You would use it like this:

const template = document.querySelector('myTemplate')
const data = { name: 'John Doe', age: 25}    
someDiv.innerHTML = interpolate(template.innerHTML.toString().trim(), data)
like image 137
Louise Eggleton Avatar answered Oct 26 '25 20:10

Louise Eggleton