Search code examples
javascriptbraces

How to display data between double braces in a set of all matches elements without using any library?


I want to make a function that can do something like this :

HTML :

 <h1 class="demo">I am {{ name }}</h1>
 <span class="demo">{{ name }} learn JavaScript</span>

JS :

data(".demo", {
   name: "Arc"
};

Output :

 I am Arc
 Arc learn JavaScript

Can the data() function be made which can do this ? I don't want to use any external library for just using this function !


Solution

  • Use a regular expression to replace {{ .. }}s in the HTML with the appropriate value in the passed object, if there is one:

    const data = (selector, obj) => {
      document.querySelectorAll(selector).forEach((elm) => {
        elm.textContent = elm.textContent.replace(
          /{{ *(\w+) *}}/g,
          // If key is in the obj, replace with the value
          // otherwise, replace with the match (make no changes):
          (match, key) => key in obj ? obj[key] : match
        );
      });
    };
    
    data(".demo", {
       name: "Arc"
    });
     <h1 class="demo">I am {{ name }}</h1>
     <span class="demo">{{ name }} learn JavaScript</span>

    If you also need to take into account nested elements, then select all text nodes of the parent, and do the same thing:

    const getTextNodes = (parent) => {
        // https://stackoverflow.com/questions/2579666/getelementsbytagname-equivalent-for-textnodes
        var walker = document.createTreeWalker(
            parent, 
            NodeFilter.SHOW_TEXT, 
            null, 
            false
        );
    
        var node;
        var textNodes = [];
    
        while(node = walker.nextNode()) {
            textNodes.push(node);
        }
        return textNodes;
    }
    
    const data = (selector, obj) => {
      document.querySelectorAll(selector).forEach((elm) => {
        getTextNodes(elm).forEach((node) => {
          node.textContent = node.textContent.replace(
            /{{ *(\w+) *}}/g,
            // If key is in the obj, replace with the value
            // otherwise, replace with the match (make no changes):
            (match, key) => key in obj ? obj[key] : match
          );
        });
      });
    };
    
    data(".demo", {
       name: "Arc"
    });
    span > span {
      background-color: yellow;
    }
    <h1 class="demo">I am {{ name }}</h1>
     <span class="demo">{{ name }} learn JavaScript <span> nested {{ name }} </span></span>