Can Es6 Template Literals Be Substituted at Runtime (Or Reused)

JavaScript template literals substitute variable later (before values are known)

No.

Template strings are for populating at the time the template string is declared.

If you want to define it early and populate it later, define it inside a function. (An option you've rejected).

You might consider another template engine such as Nunjucks or EJS … but they'll still effectively be wrapped in a function.

Is there a way to re-use a template literal in Javascript?

Simply make it to be returned by a function:

let int;let temp= () => `Number is: ${int}`;console.log(temp())// Number is: undefinedint = 1;console.log(temp())// Number is: 1int = 2;console.log(temp())// Number is: 2

Evaluating template literals dynamically

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]}`;
});

Template literals and parentheses-less function calls

In the second code snippet, these are logged:

// str
[
"Hello World ",
" ",
" ",
" and more"
]

// values
[
"John",
"John",
3
]

If by those "empty strings" you mean the 2nd and 3rd item of the str array, they are not empty strings; they are strings with a single space. They come from the spaces between the expressions in the template literal:

showstring`Hello World ${name} ${name} ${1 + 2} and more`;
// ^ ^

When a template literal is preceded by an expression – in this case showstring – it's called a tagged template.

In your showstring function, str contains always one more item than the values array. E.g. take a look at what these log:

const showstring = (str, ...values) => {
console.log(str);
console.log(values)
}
const name = 'John'
showstring``;
showstring`${name}`;
showstring`Hello ${name}!`;

Defer execution for ES6 Template Literals

I can see three ways around this:

  • Use template strings like they were designed to be used, without any format function:

    console.log(`Hello, ${"world"}. This is a ${"test"}`);
    // might make more sense with variables:
    var p0 = "world", p1 = "test";
    console.log(`Hello, ${p0}. This is a ${p1}`);

    or even function parameters for actual deferral of the evaluation:

    const welcome = (p0, p1) => `Hello, ${p0}. This is a ${p1}`;
    console.log(welcome("world", "test"));
  • Don't use a template string, but a plain string literal:

    String.prototype.format = function() {
    var args = arguments;
    return this.replace(/\$\{p(\d)\}/g, function(match, id) {
    return args[id];
    });
    };
    console.log("Hello, ${p0}. This is a ${p1}".format("world", "test"));
  • Use a tagged template literal. Notice that the substitutions will still be evaluated without interception by the handler, so you cannot use identifiers like p0 without having a variable named so. This behavior may change if a different substitution body syntax proposal is accepted (Update: it was not).

    function formatter(literals, ...substitutions) {
    return {
    format: function() {
    var out = [];
    for(var i=0, k=0; i < literals.length; i++) {
    out[k++] = literals[i];
    out[k++] = arguments[substitutions[i]];
    }
    out[k] = literals[i];
    return out.join("");
    }
    };
    }
    console.log(formatter`Hello, ${0}. This is a ${1}`.format("world", "test"));
    // Notice the number literals: ^ ^

Template Literals are not adding value together

That's because the window.getComputedStyle(el, null).getPropertyValue("padding-left") will output the value with px for example 16px, so you need to get the value as a number with parseFloat() method.

const paddingLeft = parseFloat(window
.getComputedStyle(el, null)
.getPropertyValue("padding-left"));

const el = document.querySelector('.row[data-target="row-offset"]');
const distanceFromLeft = el.offsetLeft;
const paddingLeft = parseFloat(window
.getComputedStyle(el, null)
.getPropertyValue("padding-left"));
const target = document.querySelector("#hero-carousel .flickity-page-dots");

target.style.left = `${distanceFromLeft + paddingLeft}px`;

// if (target) {
// alert("Element exists");
// } else {
// alert("Element does not exist");
// }
console.log(distanceFromLeft);
console.log(paddingLeft);
body {
font-family: sans-serif;
position: relative;
}

.row {
display: block;
background-color: pink;
width: 90%;
height: 100px;
margin: 0 auto;
}

.flickity-page-dots {
display: block;
background-color: blue;
width: 20%;
position: absolute;
left: 0;
height: 100px;
}
<!DOCTYPE html>
<html>
<head>
<title>Parcel Sandbox</title>
<meta charset="UTF-8" />
<link rel="stylesheet" href="src/styles.css" type="text/css" />
</head>

<body>
<div id="hero-carousel">
<div class="row" data-target="row-offset"></div>
<div class="flickity-page-dots"></div>
</div>

<script src="src/index.js"></script>
</body>
</html>


Related Topics



Leave a reply



Submit