[Javascript] HTML Template Interpolation
The basic interpolate
function we can create:
function interpolate(str, params) {
let names = Object.keys(params); // ["title", "description"]
let values = Object.values(params); // ["Hello", "World"]
const body = `return \`${str}\`;`; // return `<h1>${title}</h1><p>${description}</p>`;
return new Function(...names, body)(...values);
/*(function(titile, description) {
return `<h1>${title}</h1><p>${description}</p>`;
})("Hello", "World");
*/
}
const html = "<h1>${title}</h1><p>${description}</p>";
const finalHtml = interpolcate(html, {
title: "Hello",
description: "World",
});
Example:
For a web component, we have a template:
<template id="cart-item-template">
<li>
<p class="qty"></p>
<p class="name"></p>
<p class="price"></p>
<p class="toolbar">
<a href="#" class="delete-button"> 🗑️ </a>
</p>
</li>
</template>
And javascript part:
import { removeFromCart } from "../services/Order.js";
export default class CartItem extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
const item = JSON.parse(this.dataset.item);
this.innerHTML = ""; // Clear the element
const template = document.getElementById("cart-item-template");
const content = template.content.cloneNode(true);
this.appendChild(content);
this.querySelector(".qty").textContent = `${item.quantity}x`;
this.querySelector(".name").textContent = item.product.name;
this.querySelector(".price").textContent = `$${item.product.price.toFixed(
2
)}`;
this.querySelector("a.delete-button").addEventListener("click", (event) => {
removeFromCart(item.product.id);
});
}
}
customElements.define("cart-item", CartItem);
Our target is using template syntax such as Angular or React in our code:
<template id="cart-item-template">
<li>
<p class="qty">${qty}</p>
<p class="name">${name}</p>
<p class="price">${price}</p>
<p class="toolbar">
<a href="#" class="delete-button"> 🗑️ </a>
</p>
</li>
</template>
Javascript code:
import { removeFromCart } from "../services/Order.js";
export default class CartItem extends HTMLElement {
constructor() {
super();
}
connectedCallback() {
const item = JSON.parse(this.dataset.item);
this.innerHTML = ""; // Clear the element
const template = document.getElementById("cart-item-template");
const content = template.content.cloneNode(true);
// Interpolate the template with the item data
function interpolate(str, params) {
let names = Object.keys(params);
let values = Object.values(params);
const body = `return \`${str}\`;`;
return new Function(...names, body)(...values);
}
this.innerHTML = interpolate(template.innerHTML, {
qty: `${item.quantity}x`,
name: item.product.name,
price: `${item.product.price.toFixed(2)}`,
});
this.querySelector("a.delete-button").addEventListener("click", (event) => {
removeFromCart(item.product.id);
});
}
}
customElements.define("cart-item", CartItem);