0

So, there is a ES6 literal ` - backquote mark to make multiline strings with variables inside, and I need to use it with template, initially described in HTML.

<div id="template">${value}</div>

JS:

var value = 'Hello, world!'

var template = document.getElementById('template');

// Magic to convert DOM element to template string `<div id="template">${value}</div>`

console.log(element)

>>> <div id="template">Hello, world!</div>

So, I need something in "Magic" line)

4
  • Does it only contain variables or could it contain more complex expressions like real template strings? Commented Jul 16, 2018 at 19:13
  • @Barmar, no, but, honestly, just two variables Commented Jul 16, 2018 at 19:14
  • 1
    You can't, unless you're willing to use eval: var template = eval("`" + document.getElementById('template').outerHTML + "`") Commented Jul 16, 2018 at 19:15
  • Is there some averseness to using a real templating system versus re-inventing the wheel? Commented Jul 16, 2018 at 19:41

3 Answers 3

1

eval() will do what you want, although if there are expressions more complex than variables it could be dangerous.

var value = 'Hello, world!'
var template = document.getElementById('template').outerHTML;

var element = template.replace(/\$\{(\w+)\}/g, function(match, varname) {
  return window[varname];
});
console.log(element);
<div id="template">${value}</div>

If you only allow global variables in the template, you can use a regular expression.

var value = 'Hello, world!'
var template = document.getElementById('template').outerHTML;
var element = eval('`' + template + '`');
console.log(element);
<div id="template">${value}</div>

However, I recommend not using variable references at all, this is usually more general than you need. Create an object that holds all the allowed template variables, and use templateVars[varname] rather than window[varname].

Sign up to request clarification or add additional context in comments.

3 Comments

console.log(element) prints Just "Hello, world!" without div, but I need both) Btw, It works with . outerHTML instead of textContent)
@MaxCore Honestly, a short solution to this question is pretty ugly, as it’s using eval and outerHTML. A safer solution would require tons of code. Maybe it’d be better to use some other approach, instead.
@Xufox I've added a version that uses a regexp.
1

You could create this with new Function: You would pass the stringed template string you want to be converted as the body of the function:

const value = 'Hello, world!';
const template = document.getElementById('template').outerHTML;
const func = new Function('value', `return \`${template}\``);
console.log(func(value));
<div id="template">${value}</div>

1 Comment

Using new Function is just a more verbose way of doing eval().
1

Since we're re-inventing templates here, it seems a lot safer to just write your own template function that mimics a string literals, eg:

(function() {

  let tpl = document.getElementById('template-1').innerHTML

  let template = function(tpl) {
    return function(values) {
      let str = tpl.toString() //copy it

      for( let key in values ) {
       str = str.replace(v, values[key])
      }

      return str
    }
  }

  let el = template(tpl)({
     '${value}': 'test'
   })

   console.log(el)

   // <div id="myDiv">This is a test</div>

})()

//html
<!doctype html>
<html>
  <head></head>
  <body>
    <div>Hello World!</div>
    <template id="template-1">
      <div id="myDiv">This is a ${value}</div>
    </template>
   <script type="text/javascript" src="main.js"></script>
 </body>
</html>

If you need to perform validation and escaping that can be done per value. The use of eval() is certainly not recommended and you're really not buying anything by using a string literal here other than obfuscating your code.

1 Comment

Man, you are the best, specially after you first comment to a question)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.