How to use a collection of partials to insert partials based on the url? - partials

I'm using docpad with the eco templating engine and the partials plugin. The point of this is to insert a list of snippets into a landing page.
The logical approach (to me) is to iterate through a collection of the snippets and insert each snippet.
I have the following structure (following the beginner guide on adding blog posts and the partials doco):
src
├── documents
│   ├── index.html.eco
│   ├── scripts ...
│   └── styles ...
├── files...
├── layouts
│   └── default.html.eco
└── partials
├── hello.html.eco
└── world.html.eco
Contents of hello.html.eco:
---
title: "Hello"
isArticle: true
---
Hello
Contents of world.html.eco:
---
title: "World"
isArticle: true
---
World
Contents of default.html.eco (the layout)
<html>
<head>
<title>Test Partials</title>
<%- #getBlock("styles").add(["/styles/style.css"]).toHTML() %>
</head>
<body>
<h1><%= #document.title %></h1>
<%- #content %>
<%- #getBlock("scripts").add(["/vendor/jquery.js","/scripts/script.js"]).toHTML() %>
</body>
</html>
And the contents of index.html.eco:
---
title: "Welcome"
layout: "default"
isPage: true
---
<p>Welcome to my website</p>
<% for page in #getCollection("partials").findAllLive({isArticle:true}).toJSON(): %>
<article>
<%- #partial("<%= page.url %>") %>
</article>
<% end %>
As is above, docpad will crash with a Cannot read property '0' of null. However if I remove the line <%- #partial("<%= page.url %>") %> then it works.
The following line retrieves all the files in the partials directory where isArticle is set to true.
<% for page in #getCollection("partials").findAllLive({isArticle:true}).toJSON(): %>
If I change <%- #partial("<%= page.url %>") %> to <p>page.url</p> then the output lists /hello.html and /world.html, which is what I expect.
It appears that using <%- twice in one line, effectively attempting to embed some eco, is causing the problem.
Does anyone know how I can get around this? I'm trying to avoid manually coding a #partial("<filename>") for each file that I wish to be inserted. Is there a way to somehow pass to #partial the value of page.url?

The problem is not to do with the partial plugin, it's because of the second <%= statement. As we're already in eco, we don't need to escape back into eco again. So the second <%= is redundant as variables can be referenced directly.
I should have originally titled this question "How do you reference variables in eco that have been previously set".
The solution is to use the following for index.html.eco:
---
title: "Welcome"
layout: "default"
isPage: true
---
<p>Welcome to my website</p>
<% for page in #getCollection("partials").findAllLive({isArticle:true}).toJSON(): %>
<article>
<%- #partial(page.url) %>
</article>
<% end %>
As can be seen above, page.url is now referenced directly.

Related

Render EJS partial on client side - Could not find the include file error

I am trying to update with socket.io a data which is coming for some partials.
I have a partial called info_card.ejs in partials package and it has two params: title and info. I have tried rendering the following code:
<% info_cards.forEach(function(card) { %>
<%- include("../partials/info_card", card) %>
<% }); %>
The first render is made by the server, and when I am trying to render in the client side (inside a js script) as following:
const update_info_cards =
[
{title: "title1", info: "info1"},
{title: "title1", info: "info2"}
]
var html = ejs.render(`<% info_cards.forEach(function(card) { %>
<%- include("../partials/info_card", card) %>
<% }); %>`, {info_card: update_info_cards })
I get this error:
1| <% info_cards.forEach(function(card) { %>
>> 2| <%- include("../partials/info_card", card) %>
3| <% }); %>
Could not find the include file "../partials/info_card"
Don't know how to fix it, I have tried to change the path for such a long time, but still get this error. I have also tried to look up for some answers on the internet - couldn't find any.
I saw that I can't do include on client side, so what's the alternative, because I really can't see me coping all the html code of the card multiple times?
Thanks!

Unexpected token '/' in {FILE} while compiling ejs

I am working on this: https://www.youtube.com/watch?v=6FOq4cUdH8k
For some reason, the following line is causing the error in the title.
<% include ./partials/messages %>
Removing the line above solves the problem.
I have confirmed that it is not the messages file as there are no slashes in it.
<% if(typeof errors != 'undefined') { %>
<% errors.forEach(function(error){ %>
<%= error.msg %>
<% }); %>
<% } %>
as you can read in the official documentation
Includes are relative to the template with the include call. (This
requires the 'filename' option.) For example if you have
"./views/users.ejs" and "./views/user/show.ejs" you would use <%-
include('user/show'); %>.
You'll likely want to use the raw output tag (<%-) with your include
to avoid double-escaping the HTML output.
so instead of
<% include ./partials/messages %>
Write
<%- include ("./partials/messages") %>
Why?
Template tag <%- outputs the unescaped value into the template, whereas <% 'scriptlet' tag is used for control-flow, no output. The parenthesis and " " are used for filename location

SyntaxError: Unexpected identifier when using ejs in nodejs

I am following The Net Nijna's tutorial on youtube.
I reached tutorial number 27, working with partials in ejs. Everything works until I add the <% include partials/nav.js %>, once I add this code I recieve:
SyntaxError: Unexpected identifier in (file location) testapp\views\profile.ejs while compiling ejs
If the above error is not helpful, you may want to try EJS-Lint:
https://github.com/RyanZim/EJS-Lint
Or, if you meant to create an async function, pass async: true as an option.
at new Function ()..... blah blah blah...
If I remove it, my ejs all works fine.
<body>
<% include partials/nav.ejs %>
<h1>Welcome to the profile of <%= person %> !</h1>
<p><strong> Age: <%= data.age %></strong></p>
<p><strong> Job: <%= data.job %></strong></p>
<p><strong> Pet: <%= data.pet %></strong></p>
<h2>Hobbies</h2>
<ul>
<% data.hobbies.forEach(function(item){ %>
<li><%= item %></li>
<%});%>
</ul>
</body>
can you help a student out? Thanks a ton!
Missing hyphen and need to invoke the include function.
<%- include('partials/nav') %>
I was stuck at the same problem and used -include('#filename');
it worked
Use: <%- include('folder/file') %>
agreeing with #Joseph Varilla
Not necessary to include engine extension as this should have been done in app.js or index.js file

EJS: Pass array of pages into include(page)

I've created a dashboard page where a user can save different components of the site to one page for quick viewing. I'm able to dynamically load one component as follows:
index.js
res.render('dashboard',{comp: 'component1'});
dashboard.ejs
<%- include(comp) %>
but I would like to do something like this:
index.js
res.render('dashboard',{comp: ['component1', 'component3']});
And have the ejs page loop through the include(), this way i can show 0 to n components on the dashboard page.
I've tried wrapping the include in a for loop like so:
<%- for(c in comp){include(c)} %>
but ejs did not like this.
Am I going about this the wrong way?
Try this
<% for(var i=0; i < comp.length; ++i) { %>
<%- include(comp[i]) %>
<% } %>
in your code, c is the index not value, comp[c] is your component.
<% for(c in comp){ %>
<%- include(comp[c]) %>
<% } %>

How to place an EJS tag within another

I am using EJS as my templating engine. I am passing variables from node js to ejs like...
router.get("/AdminDatabase", function(req, res) {
res.render('Pages/AdminDatabase', {title: 'WebFormsAdmin', role: 'System Admin' });
});
I am building a role base control and for this I want to change the header of the page base on the role of user.
<% include ../partials/Common/header_<%= role %> %>
The problem is with the above segment. How can I place the variable role inside this EJS code segment?
My header files are
header_System Admin.ejs,
header_Survey Admin.ejs,
header_Survey Taker.ejs
A workaround would be to do a conditional render like so:
<% switch (role) {
case 'System Admin': %>
<% include ./partials/header_System_Admin %>
<% break; %>
<% case 'Survey Admin': %>
<% include ./partials/header_Survey_Admin %>
<% break; %>
<% default: %>
<% include ./partials/header_Survey_Taker %>
<% break; %>
<% } %>
Note that the first case must be grouped with the switch declaration. Make sure the paths are correct for your partials.
You can concatenate the path and the variable.
<%- include('../partials/Common/header_'+role) %>

Resources