Использование интерполяции внутри Node.js EJS включает

Приложение My Express использует EJS, а мой каталог представлений выглядит следующим образом:

./views
  ./contents
    home.ejs
  ./includes
    header.ejs
    footer.ejs
  layout.ejs

Я пытаюсь загрузить home.ejs в свой layout.ejs, условно основанный на локальной переменной с именем contents в моих маршрутах /index.js. Этот файл выглядит следующим образом:

/*
 * GET home page.
 */

exports.index = function(req, res){
  res.render('index', { title: 'Home', contents: 'home.ejs' });
};

В идеале я мог просто написать (в layout.ejs):

<% include '/contents' + contents %>

где конечное "содержимое" - это локальная переменная, которая содержит относительный путь к тексту тела, который требуется загрузить.

Но, увы, похоже, EJS всегда интерпретирует текст, следуя директиве include буквально, и нет никакой возможности для какой-либо магии интерполяции.

Я также пытался безрезультатно:

<% function yieldContent(contents){ %>
  <% var contentPath = 'contents/' + contents; %>
  <% include contentPath %>
<% }; %>
<% loadContent(); %>

Есть ли у кого-нибудь креативное решение для условного включения представления на основе переменной, передаваемой по маршрутам?

Ответы

Ответ 1

Я думаю, что в EJS такой способ не существует. Это может нарушить разделение бизнес-логики и взгляда. Решение может состоять в том, чтобы сделать подтеку в контроллере и передать его содержимое в макет.

Для рендеринга подматрицы в контроллере используйте что-то вроде этого:

var ejs = require('ejs'),
, fs = require('fs')
, home = ejs.render(fs.readFileSync("contents/home.ejs", "utf-8"))

Ответ 2

В версии 2 EJS функция include делает это хорошо. С его помощью включенные вставляются во время выполнения, поэтому переменные могут использоваться как пути.

В этом случае решение может быть:

<%- include('contents/' + contents) %>

При необходимости функция может иметь и другой аргумент:

<%- include('mypathname', {foo:"bar"}) %>

Имя пути должно относиться к шаблону, который вызывает функцию.

Ответ 3

В настоящее время это не реализовано в ejs, но есть этот запрос на обсуждение и pull, который предлагает функциональность.

https://github.com/visionmedia/ejs/issues/93

Ответ 4

в вашей функции рендеринга вы можете включить fs.readFileSync и __dirname.

Отобразить страницу с такими параметрами

res.render('pages/'+req.file,{file_get_contents:fs.readFileSync,__dirname:__dirname});

Затем вы можете использовать его на странице .ejs следующим образом. Это остается на стороне сервера.

<% var products=JSON.parse(file_get_contents(__dirname+'/web/data/products.json','utf8')) %>

Вы можете распечатать данные на клиентском HTML, как это.

<%- JSON.stringify(products)%>

Примечание. Использование этого метода означает, что у вас есть fs, который находится где-то в верхней части вашего script.

var fs = require('fs')