app.js (node process, includes etc excluded for brevity but using ejs as rendering engine):
app.get('/', function(req, res){
var ejsVariables = {
title : 'ideal ejs function example',
listData1 : {
listTitle : 'my list',
listItems : [
{ name : 'first item', class : 'foo' },
{ name : 'second item', class : 'bar' },
{ name : 'last item', class : 'foo' } ]
},
listData2 : {
listTitle : 'your list',
listItems : [
{ name : 'a widget', class : 'foo' },
{ name : 'another widget', class : 'baz' }
]
}
};
res.render('index', ejsVariables);
});
index.ejs:
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h1><%= title %></h1>
<% makeList(listData1) %>
<p>lorem ipsum</p>
<% makeList(listData1) %>
</body>
</html>
???
result:
<html>
<head>
<title>ideal ejs function example</title>
</head>
<body>
<h1>ideal ejs function example</h1>
<ul>
<li class="foo">first item</li>
<li class="bar">second item</li>
<li class="foo">another item</li>
</ul>
<p>lorem ipsum</p>
<ul>
<li class="foo">a widget</li>
<li class="baz">another widget</li>
</ul>
</body>
</html>
What I've tried so far
index.ejs
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h1><%= title %></h1>
<% var makeList; %>
<!-- this variable is declared here as those declared within the include are not
accessible from the file from which it is called, I'm guessing some sort of
function scope is coming into play here -->
<% include makeList %>
<% makeList(listData1) %>
<p>lorem ipsum</p>
<% makeList(ListData2) %>
</body>
</html>
makeList.ejs
<% function makeListItem(itemData){ %>
<li class="<%= itemData.class %>" ><%= itemData.name %></li>
<% } %>
<% makeList = function(data){ %>
<% if(data){ %>
<ul>
<% data.map(makeListItem) %>
</ul>
<% } %>
<% } %>
In this situation both makeListItem
and makeList
are being called, it just appears that due to scoping or something else, when they come to be called they are unable to actually output to the template.
index.ejs
<html>
<head>
<title><%= title %></title>
</head>
<body>
<h1><%= title %></h1>
<% var data = listData1 %>
<% include makeList %>
<p>lorem ipsum</p>
<% var data = listData2 %>
<% include makeList %>
</body>
</html>
makeList.ejs
<% function makeListItem(itemData){ %>
<li class="<%= itemData.class %>" ><%= itemData.name %></li>
<% } %>
<% if(data){ %>
<ul>
<% data.map(makeListItem) %>
</ul>
<% } %>
If I'm going to include another npm module in my application I'd really want it to be a more complete solution, but even then in an ideal world I'd rather do without and write it myself.
Apologies for the length of this post, it got out of hand quite quickly. I commend you if you've got this far.
Any input would be greatly appreciated.
How about this:
// app.js
var ejs = require('ejs');
var fs = require('fs');
app.locals({
makeList : function(list) {
var template = fs.readFileSync('makeList.ejs', 'utf-8');
return ejs.render(template, list);
}
});
// index.ejs
<%- makeList(listData1) %>
^ important!
// makeList.ejs
<ul>
<% listItems.forEach(function(item) { %>
<li class="<%= item.class %>"><%= item.name %></li>
<% }); %>
</ul>