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
Ajax, Back Button and Dom Updates
When Does Js Interpret {} as an Empty Block Instead of an Empty Object
Chrome Extension - Sendresponse Not Waiting for Async Function
JavaScript Print Iframe Contents Only
Get First and Last Date of Current Month with JavaScript or Jquery
How to Parse JSON to Receive a Date Object in JavaScript
Mobile Safari Autofocus Text Field
Calling a JavaScript Function Named in a Variable
How to Create a Function from a String with JavaScript
Javascript: Which Browsers Support Parsing of Iso-8601 Date String with Date.Parse
Cross-Origin Read Blocking (Corb)
Object Method with Es6/Bluebird Promises
Javascript: Formatting a Rounded Number to N Decimals