[Javascript] HTML Template Interpolation

Zhentiw發表於2024-08-20

The basic interpolatefunction 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);

相關文章