2

I have a template Hello, ${user.name} stored in a variable. I am reading this from an external file using fs.read.

Now, obviously when I attach to the innerHTML of a target div, it shows the string as it is and not "Hello, James" (assuming user.name = James) as intended.
Is there a way to make it happen?

extfile.txt =>
{"A":"`Welcome, ${user.name}`"}

Node.js code =>

fs.readFile(__dirname + '/extfile.txt', 'utf8', function (err,data) {
  if (err) {
    return console.log(err);
  } else {
    let x = JSON.parse(data);
    socket.emit('var',x.A);
  }
});

HTML =>

socket.on('var',function(x)){
  getElementById('target').innerHTML = x;
}
benomatis
  • 5,536
  • 7
  • 36
  • 59
Piyush Pandey
  • 306
  • 3
  • 17
  • You use the character ` for template literals, not " – nicovank Dec 10 '16 at 03:15
  • What template mechanism are you using? JavaScript template literals? If so, it'd be `Hello, ${user.name}` and it will not work because template literals are compile-time, not run-time. – cartant Dec 10 '16 at 03:18
  • @cartant "Compile time"? JS is interpereted... template arguments are evaluated every time the template literal is evaluated – qxz Dec 10 '16 at 03:19
  • @rookie Can you show us more complete JS/HTML that demonstrates what you're trying to do? – qxz Dec 10 '16 at 03:20
  • @qxz Fair point. Interpretation-time, then. The issue is that template literals are just that: literals. You cannot use strings stored in variables. – cartant Dec 10 '16 at 03:21
  • I am using the default JavaScript template literal. – Piyush Pandey Dec 10 '16 at 03:22
  • @cartant The point of template literals is that they can substitute dynamic data... See [JSFiddle](https://jsfiddle.net/edbp7jdf/) – qxz Dec 10 '16 at 03:26
  • @rookie Can you give us an idea of the broader feature you're trying to implement? Perhaps [edit](http://stackoverflow.com/posts/41071779/edit) to show us your current complete code? – qxz Dec 10 '16 at 03:29
  • @qxz Yes, I am aware of that, but the OP's first sentence states that the template is stored in a *variable* and that is the problem. It is not a template *literal*. – cartant Dec 10 '16 at 03:29
  • That's fair. I am reading a json from an external file. {"A":"`Hello, ${user.name}"}. Let x = (JSON from the file). Now when I document.getElementById('target').innerHTML = x.A, I expected it to substitute the user.name from an existing variable. It did not do it. How can I make that happen. PS: Please, Ignore the typos/error, typing from a phone and not my workstation. – Piyush Pandey Dec 10 '16 at 03:34
  • @cartant hi, have edited the question to include the code showing what i am precisely doing. Am still stuck. Thanks in advance. I am open to any alternate way of looking to the problem as well. – Piyush Pandey Dec 10 '16 at 05:32
  • 1
    This question may help you: http://stackoverflow.com/questions/34882100/can-you-dumb-down-es6-template-strings-to-normal-strings/34883543#34883543 –  Dec 10 '16 at 07:19

3 Answers3

5

I've slightly rewritten a solution presented here.

Here, eval_template evaluates an ES6 template string provided as a regular string. Any variable in local scope used in the template string needs to be provided as a property of the object passed in the second parameter (because functions created using Function are in the global scope and cannot access local variables).

This is perilously close to using eval. You might want to choose a different approach to handling your template strings. ES6 template strings are designed to be a run-time mechanism to create string literals, not a templating language whose templates can be stored and re-used.

function eval_template(s, params) {
  return Function(...Object.keys(params), "return " + s)
    (...Object.values(params));
}

const template = "`Welcome, ${user.name}`";
console.log(eval_template(template, {user: {name: "James"}}));

There is no reason this could not be used with a tagged template string, as long as the tag is passed in as a parameter:

eval_template("tag`${boo}`", {tag, boo});
Community
  • 1
  • 1
1

I also had this problem sometimes when I have my labels variables in another file, and those labels should have a template literal. I this cases I usually use a workaround to simulate this behaviour (take this code as a guide :D )

labels.js:

export default:{
    labelWithSpeudoliteral: "text to {{change}}"
}

MyHelper.js:

    generateLiteral(s, params) {
        const entries = Object.entries(params);
        let sentence = s;
        entries.forEach((entry) => {
                const literal = `{{${entry[0]}}}`
                sentence = sentence.replace(literal, entry[1]);
            }
        )
        return sentence;
    }

Now in my code I use this helper the following way:

console.log(generateLiteral(labels.labelWithSpeudoliteral, {'change': 'literal'})

And the result of the label should be:

text to literal

As you can see using the {{ }} symbols as marks, generateLiteral() use them and the params received to change the text value with the template literal. It is not the best way, but I hope it can help you.

Mest
  • 99
  • 2
  • 6
0

Template literals need a $, not an ampersand. Also, remember to use backticks and not quotes.

davidatthepark
  • 1,235
  • 1
  • 13
  • 25