I am passing an array of objects to an EJS template, which I would like to map into links using the regular .map() method of arrays. But for reasons I can't figure out, the callback I'm passing to map() doesn't work within EJS the way I'd expect, and I'm getting empty results.
My data is an array of objects, each with a "section" and a "name" key. This array is passed as "entries" to the template:
siteHeaders = [ { section: "home", name: "Home"},
{ section: "about", name: "About Me"},
... plus few more ]
The template looks like this, and I have it in a local variable called (surprise) template
:
<% entries = entries.map(function(elem) { -%>
<% return -%>
<a href="/<%= elem.section %>">
<%= elem.name %>
</a>
<% } ) -%>
<p><%- entries.join(" | ") %></p>
The result of this template, when I call require('ejs').render(template, {entries: siteHeaders})
is:
<p> | | | | </p>
What I don't get is why this doesn't work in an EJS template, when the corresponding map call works just fine in REPL:
> siteHeaders.map(function(e){ return '<a href="/' + e.section +'">' + e.name + '</a>' })
[ '<a href="/home">Home</a>',
'<a href="/guide">About Me</a>',
'<a href="/quickstart">Portfolio</a>',
'<a href="/reference">Blog</a>',
'<a href="/downloads">Contact</a>' ]
>
Any clues?
EJS (Embedded JavaScript Templating) is one of the most popular template engines for JavaScript. As the name suggests, it lets us embed JavaScript code in a template language that is then used to generate HTML.
The map() method calls a callback function on every element of an array and returns a new array that contains the results. The map() method takes two named arguments, the first one is required whereas the second one is optional.
Looping Over Data in EJSTo loop over data, you can use . forEach .
This code should work:
<% entries = entries.map(function(elem) {
return '<a href="/' + elem.section + '">' + elem.name + '</a>';
}) -%>
<p><%- entries.join(" | ") %></p>
You can't use simple html inside of functions. It's possible only in loops and conditions.
It's not as clean as join(' | '), but if you don't want to concatenate, you can do this:
<% entries.forEach(function(entry, i, entries){ %>
<a href="<%= entry.section %>"><%= entry.name %></a>
<%= i == entries.length-1 ? ' | ' : '' %>
<% } %>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With