I want to use a template literal, i.e. backticks, to insert elements from an array into my HTML. Essentially, I want to create my own extremely simple templating system.
I expected forEach
to work, with each iterated callback just inserting the returned text. However, it just returns undefined
, e.g.:
const myArray = ['square', 'triangle', 'circle'];
document.querySelector('div').innerHTML = `
<p>Some shapes:<\p>
<ul>
${myArray.forEach(elmt => `
<li>${elmt}</li>
`)}
</ul>
`;
<div></div>
I want to use a template literal, i.e. backticks, to insert elements from an array into my HTML. Essentially, I want to create my own extremely simple templating system.
I expected forEach
to work, with each iterated callback just inserting the returned text. However, it just returns undefined
, e.g.:
const myArray = ['square', 'triangle', 'circle'];
document.querySelector('div').innerHTML = `
<p>Some shapes:<\p>
<ul>
${myArray.forEach(elmt => `
<li>${elmt}</li>
`)}
</ul>
`;
<div></div>
So, how do I do this?
Share Improve this question edited May 29, 2018 at 11:35 Andrew Willems asked May 29, 2018 at 0:26 Andrew WillemsAndrew Willems 12.5k10 gold badges56 silver badges73 bronze badges1 Answer
Reset to default 6Use myArray.map(...).join('')
instead of myArray.forEach(...)
.
In a template literal, the results of code within a placeholder, i.e. within ${...}
, are coerced to a string before insertion. A forEach(...)
loop only returns undefined
by definition. In contrast, map(...)
returns a use-able value, i.e. an array. However, when the array is co-erced to a string, by default mas are inserted between elements. This results in unwanted text nodes, each containing a ma, appearing between the intended insertions. However, this default can be changed by explicitly joining the array elements with an empty string using .join('')
:
const myArray = ['square', 'triangle', 'circle'];
document.querySelector('div').innerHTML = `
<p>Some shapes:<\p>
<ul>
${myArray.map(elmt => `
<li>${elmt}</li>
`).join('')}
</ul>
`;
<div></div>
Note that this strategy can easily be used with other iterables by first simply coercing them to an array, e.g. by using [...mySet].map...
instead of myArray.map...
, etc.