Alexander Mills
Alexander Mills

Reputation: 100070

Evaluating template literals dynamically

Say I have template literal like so:

const templateLiteral = `string text ${expression} string text`

I want to dynamically evaluate the template literal into a finished string.

function toFoo(templateLiteral){
   //returns "string text Foo string text"
   return templateLiteral.evaluate('Foo');  
}

function toBar(templateLiteral){
  //returns "string text Bar string text"
   return templateLiteral.evaluate('Bar');  
}

function toBaz(templateLiteral){
   //returns "string text Baz string text"
   return templateLiteral.evaluate('Baz');  
}

is there a way to do something like this with template literals, or am I just being dumb? (template.evaluate() is a made up function, but I am looking for that kind of functionality with JS!).

Upvotes: 14

Views: 7816

Answers (4)

GMKHussain
GMKHussain

Reputation: 4681

Reusable and simplified templating function with dynamic values.

const contentTemplate = (template, dynamicValues, callback, selector) => {
  const regex = /{{(.*?)}}/g;
  const result = template.replace(regex, (match, captureKey) => { 
    return dynamicValues[captureKey] || '';
  })
  callback && callback(result, selector)
  return result
}

const content = 'Hello, My is {{name}}, age is {{age}} and Im from {{city}}';
const dynamicValues = {
  name: 'Amoos',
  age: 28,
  city: 'Paris'
}

const addContentFunction = ( tranformedContent, selector ) => {
  const app = document.querySelector(selector)
  app.innerHTML = tranformedContent ? tranformedContent : 'No content!'
}

contentTemplate(content, dynamicValues, addContentFunction, '#myId')
contentTemplate(content, {name: 'Rifat', age: 24, city: 'Berlin' }, addContentFunction, '.myClass')
<div id="myId"></div>
<hr />
<div class="myClass"></div>

Upvotes: 0

notion
notion

Reputation: 686

Tagged template strings could help in this scenario:

function toFoo(strings, ...values) {
    console.log(strings[0]); // string text
    console.log(strings[1]); // string text
    console.log(values[0]);  // <your-passed-expression>

    // TODO: Do your manipulation
}

const val = toFoo`string text ${expression} string text`;

strings contains the "normal" tokens of the line and values are the "variable" parts. Please note that you have to concatenate the string manually.

Upvotes: 1

Alexander Mills
Alexander Mills

Reputation: 100070

The best way to do this is quite obvious, simply reverse the situation given by the question. You just need to wrap the template literals in a function, and then you will delay evaluation until you pass in the desired params. It's that simple.

function evaluteTemplateLiteral(bar){
  return `foo ${bar} baz`;
}

now if you wanted to get fancier, you could create this:

function evaluateGeneric(vals, fn){
   return fn.apply(null, vals);
}

and you would use the above like so:

evaluateGeneric(['brown','fox','cholo'], function(){
    return `the quick ${arguments[0]} fox ${arguments[1]}`;
});

Upvotes: 12

Martijn Scheffer
Martijn Scheffer

Reputation: 691

i would just call eval, you are evaluating code anyway when using template strings

Upvotes: 0

Related Questions