Функции в ejs

То, что я хотел бы иметь, выглядит примерно так:

app.js (node процесс, включает и т.д. исключен для краткости, но с использованием ejs в качестве механизма рендеринга):

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>

???


результат

<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>

Вопрос: что происходит в??? раздел и/или должны быть изменены выше?


Что я пробовал до сих пор

Попытка 1

- Я действительно хочу, чтобы это сработало, просто не

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>
    <% } %>
<% } %>

В этой ситуации вызывается как makeListItem, так и makeList, просто появляется, что из-за видимости или чего-то еще, когда они вызывают их, они не могут фактически выводить на шаблон.


Попытка 2

- это действительно работает, мне просто не нравится, как я в конечном итоге использую include вместо какого-то вызова функции.

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>
<% } %>

Попытка 3

- это в основном связано с использованием ejs-locals, однако я обнаружил, что функциональность несколько отсутствует.

Если я собираюсь включить другой модуль npm в мое приложение, я бы действительно хотел, чтобы это было более полное решение, но даже тогда в идеальном мире я бы предпочел обойтись и написать сам.


Извиняясь за длину этого поста, он быстро вышел из-под контроля. Я благодарю вас, если вы зашли так далеко.

Приветствуется любой ввод.

Ответ 1

Как насчет этого:

// 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>

Ответ 2

Единственное, о чем я могу думать (по крайней мере, для первого примера) - это функция makeList(), удаляющая listData1 из ejsVariables, можете ли вы показать мне makeList() для этого примера?

В попытке 1 вы вызываете makeList() без параметра!