Как передать пользовательский объект партиалам в ejs?

Я пытаюсь отобразить имя пользователя на панели навигации, но эта панель навигации находится в частичной папке, и ни один из маршрутов в node.js не отображает navbar.ejs, потому что это всего лишь частичная. Я использую библиотеку ejs-mate для многократного использования компонента макета для других компонентов html, чтобы мне не нужно было копировать и вставлять коды (следуя принципу DRY), почему? потому что ejs не имеет встроенной функции многократно используемого компонента макета, а другие библиотеки не поддерживаются другими разработчиками.

В настоящее время

у меня два маршрута

app.get('/', passport.isAuthenticated, function(req, res) {
   res.render('home' {
     user: req.user
   });
});

app.get('/anotherRoute', function(req, res) {
   res.render('test');
});

У меня есть два файла ejs

home.ejs

<%- layout('boilerplate') %>

<h1>Home Page</h1>

другой.ejs

<%- layout('boilerplate') %>

<h1>Another Page</h1>

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

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

<!DOCTYPE html>
<html lang="en">
<head>

    <% include ./partials/navbar %>
</head>
<body>

    <header>
        <% include ./partials/header %>
    </header>

<div class="container">
    <main>
        <%- body -%>
    </main>

    <footer>
        <% include ./partials/footer %>
    </footer>
  </div>

</body>
</html>

Это файл навигационной панели, взгляните на класс navbar-right,

if user is logged in render name 
else render about and signup

navbar.ejs

<nav class="navbar navbar-default" role="navigation">
    <div class="container-fluid">

        <div class="navbar-header">
            <a class="navbar-brand" href="/">
                StartupClone
            </a>
        </div>

        <ul class="nav navbar-nav navbar-right">
            <li><a href="/">About</a></li>
            <% if (!user) { %>

            <li><a href="/signup">Signup</a></li>
            <li><a href="/login">Login</a></li>
        </ul>
        <% } else{ %>
          <li><a><%= user.profile.name %></a></li>
       <% } %>
    </div>
</nav>

Проблема сейчас заключается в работе только с маршрутом, по которому я передаю объект пользователя, но не с другими маршрутами. Я знаю, что мне нужно передать объект пользователя на каждый отдельный маршрут, но это нехорошо, потому что мне снова нужно копировать и вставлять коды снова в каждый отдельный маршрут, что противоречит принципу DRY,

Представьте, если бы у меня было 40 маршрутов, которым нужно использовать эту панель навигации, это было бы для меня кошмаром :(

Если у вас, ребята, есть какие-либо идеи о том, как это взломать, не стесняйтесь делиться своими мыслями о том, как решить эту проблему.


person Jack Moscovi    schedule 30.09.2015    source источник
comment
expressjs.com/guide/using-template-engines.html первый аргумент render() — это шаблон, тогда как остальные аргументы — это переменные, которые вы хотите сделать доступными в шаблоне.   -  person Gaurav Gupta    schedule 30.09.2015


Ответы (2)


Обязательно передать объект, к которому вы пытаетесь получить доступ, в представлении. Одна вещь, которую вы можете сделать, это сохранить пользовательский объект в сеансе и просмотреть сеанс проверки для пользовательского объекта. Таким образом, вам нужно будет передать только объект сеанса, по крайней мере, я использую этот трюк для этой проблемы.

В вашем промежуточном программном обеспечении Passport.isAuthenticated при успешном входе в систему сохраните объект пользователя в сеансе.

module.exports.isAuthenticated = function(req, res, next) {
  /*
     check for valid credentials 
  */
  if (success)
  {
    req.session.user = foundUserInfo;
  }
  next();
}

и в вашем частичном представлении

<!-- navbar.ejs -->
<nav class="navbar navbar-default" role="navigation">
<div class="container-fluid">

    <div class="navbar-header">
        <a class="navbar-brand" href="/">
            StartupClone
        </a>
    </div>

    <ul class="nav navbar-nav navbar-right">
        <li><a href="/">About</a></li>
        <% if (!session.user) { %>

        <li><a href="/signup">Signup</a></li>
        <li><a href="/login">Login</a></li>
    </ul>
    <% } else{ %>
      <li><a><%= session.user.profile.name %></a></li>
   <% } %>
</div>

Now you just have to pass session object for each route.

app.get('/', passport.isAuthenticated, function(req, res) {
   res.render('home' {
      user: req.user,
      session: req.session
   });
});

app.get('/anotherRoute', function(req, res) {
   res.render('test', {session: null});
});
person Riyaz Parve    schedule 30.09.2015

Вы должны передавать объект с используемыми свойствами для каждого вызова res.render(), без этого не обойтись. Это даже в примере использования в документации ejs-mate.

Сказав это, есть способ сохранить ваш код СУХИМ. Используйте функцию, которая устанавливает общие свойства для входного объекта, а затем для каждого маршрута задайте уникальные свойства, которые ему требуются:

function setSharedProperties(req, data) {
   if(!(data instanceof Object)) {
      data = {};
   }
   data.user = req.user;

   return data;
}

app.get('/', passport.isAuthenticated, function(req, res) {
   res.render('home', setSharedProperties(req))
});

app.get('/anotherRoute', function(req, res) {
   res.render('test', setSharedProperties(req, {prop1: val1}));
});
person Amit    schedule 30.09.2015