Ejs doesn't render ejs file - node.js

I want to make a queue system for to create pdf file. I created a node server and used Express framework. Also I used rabbitmq for the queue system. I set view engine ejs
app.set('view engine', 'ejs');
app.use(Express.static(__dirname + "/views"));
My folder structure is
consumers
--consumer_report.js
views
report.ejs
report
--environment.ejs
--consultans.ejs
--map.ejs
When a user wants to create a pdf, I redirect it to the queue. The queue is calculating some datas. After calculating I'm using render ejs file.
createReport(msg.user, msg.reportID, msg.type, msg.packetName, (err, data) => {
data.packet = msg.packetName;
let dirUrl = __dirname + "/../views/report.ejs";
let opts = {
async: true
}
ejs.renderFile(dirUrl, data, opts, (err, html) => {
if (err) return console.error(err);
console.log("html", html);
});
});
Report Ejs
<!DOCTYPE html>
<html lang="en" style="zoom:0.75;">
<head>
<meta charset="UTF-8">
<title>Report</title>
<link rel="stylesheet" href="<%= host %>/css/rp.css">
<script src="<%= host %>/js/jquery3.2.1.min.js"></script>
<script src="<%= host %>/js/highcharts.js"></script>
<script src="<%= host %>/js/rp.js"></script>
</head>
<body>
<% for(let i of index){brackets = i.i_page; title= i.name %>
<% if(brackets=="environment") {%> <%- include report/environment.ejs %> <% } %>
<% if(brackets=="consultant") {%> <%- include report/consultants.ejs %> <% } %>
<% if(brackets=="map") {%> <%- include report/map.ejs %> <% } %>
<% } %>
</body>
</html>
When render the ejs file I get this error
Error SyntaxError: missing ) after argument list in /home/aaa/Desktop/projects/report/consumers/../views/report.ejs while compiling ejs
I couldn't find the error. Where is my mistake?

you need to change include syntax to include(path), as per docs:
NOTE: Include preprocessor directives (<% include user/show %>) are
not supported in v3.0+.
https://github.com/mde/ejs
try this:
<!DOCTYPE html>
<html lang="en" style="zoom:0.75;">
<head>
<meta charset="UTF-8">
<title>Report</title>
<link rel="stylesheet" href="<%= host %>/css/rp.css">
<script src="<%= host %>/js/jquery3.2.1.min.js"></script>
<script src="<%= host %>/js/highcharts.js"></script>
<script src="<%= host %>/js/rp.js"></script>
</head>
<body>
<% for(let i of index){brackets = i.i_page; title= i.name %>
<% if(brackets=="environment") {%> <%- include('report/environment.ejs') %> <% } %>
<% if(brackets=="consultant") {%> <%- include('report/consultants.ejs') %> <% } %>
<% if(brackets=="map") {%> <%- include('report/map.ejs') %> <% } %>
<% } %>
</body>
</html>

Related

How to Fix Node Js Missing Arguments in index.ejs File

I am working on an eWallet with Node Js and I have found a bug that I can't figure out what is the issue.
Here is the code for index.ejs:
`<!DOCTYPE html>
<html>
<head>
<meta charset="urf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="author" content="Mr. Barasa Joel">
<meta name="description" content="eWallet - Free E-Wallet">
<meta name="keywords" content="E-Wallet, digital wallet, wallet">
<link rel="shortcut icon" href="img/favicon.ico">
<link rel="stylesheet" href="css/styles.css">
<title>E-Wallet</title>
</head>
<% if(page == 'home') { %><section class="image"><% } %>
<header class="header-columns header-filled header-mobile">
<img src="/img/icon-menu.png" alt="" height="24" id="mobile-menu">
<article class="header-columns header-left">
<img src="img/logo-full.png" alt="ewallet" height="40">
</article>
<article class="header-center">
<nav>
<ul class="header-columns menu">
<li>O eWallet</li>
<li>How it's working</li>
<li>Where will you pay</li>
</ul>
</nav>
</article>
<article class="header-columns header-right">
Create an account
Log in
</article>
</header>
<% if(page == 'home') { %></section><% } %>
<body <% if(page != 'home') { %>class="app-body gradient"<% } %>>
<% if(page == 'home') { %>
<%- include home %>
<% } else if(page == 'login') { %>
<%- include login %>
<% } else if(page == 'register') { %>
<%- include register %>
<% } %>
<footer class="footer-fixed-bottom">Copyright © 2023 Mr. Barasa Joel</footer>
<script src="/js/mobile-menu.js"></script>
</body>
</html>`
When I try to run the app on the browser, I get this error:
The error displayed is:
Error: missing ) after argument list in "Node\eWallet\views\index.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.
Error displayed

Express nodejs Handlebars not rendering database content correctly inside EJS file

Im having a problem with my express nodejs project where the handlebars wont render on my ejs file. I created some handlebars which fetch some data from a database. When I render the hbs files the content from the database is displayed correctly, but when I include the hbs files in my ejs file together with my page header and footer the content from the database is not retrieved. I would appreciate any help.
cars.hbs
<!DOCTYPE html>
<html>
<body>
<p> The {{dbcars.model}} features a {{dbcars.specs.engine}} engine... </p>
</body>
</html>
home.ejs
<body>
<p> <%- include('navbar.ejs') %> </p>
<p> <%- include('handlebars/cars.hbs') %> </p>
<p> <%- include('footer.ejs') %> </p>
</body>
</html>
(note: when I render (handlebars/cars.hbs) instead of (home.ejs) the handlebars render correctly. )
car.js
router.get('/vehicle/:id', async (req, res) => {
Car.findById(req.params.id, function(err, carRouter) {
res.render("home.ejs", {
dbcar: carRouter
})
This is the result im getting:
(navbar)
The {{dbcars.model}} features a {{dbcars.specs.engine}} engine...
(footer)
This is the result im trying to get:
(navbar)
The Nissan Sentra features a 2.0 L 4-cylinder engine...
(footer)
You should create cars.ejs as well
cars.ejs
<% if (dbcar.length > 0) { %>
<% dbcar.forEach(dbcars => { %>
<p> The <%= dbcars.model %> features a <%= dbcars.specs.engine %> engine... </p>
<% }) %>
<% } else { %>
<p>There is no information to display.</p>
<% } %>
home.ejs
<%- include('handlebars/cars.ejs'); %>
car.js
router.get('/vehicle/:id', async (req, res) => {
Car.findById(req.params.id, function(err, carRouter) {
res.render("cars.ejs", {
dbcar: carRouter
})
};
};

EJS not able to render page due to class declaration

<header class="main-header">
<nav class="main-header__nav">
<ul class="main-header__item-list">
<li class="main-header__item"><a class="<%= path === '/' ? 'active' : '' %>" href="/">Shop</a></li>
<li class="main-header__item"><a class="<%= path === '/admin/add-product' ? 'active' : '' %>" href="/admin/add-product">Add Product</a></li>
</ul>
</nav>
When I try to render the page in my node js application I am getting an error. Saying there is an error
I am not so used to writing ejs but when I remove the class="<%= path === '/' ? 'active' : '' %>" in the navigation.ejs it seems to work
Error Image
Use <%- include('RELATIVE/PATH/TO/FILE'); %> to embed an EJS partial in another file.
The hyphen <%- instead of just <% tells EJS to render raw HTML.
The path to the partial is relative to the current file.
and also use ; at end of include
Here is an example...
<!DOCTYPE html>
<html lang="en">
<head>
<%- include('../partials/head'); %>
</head>
<body class="container">
<header>
<%- include('../partials/header'); %>
</header>
<main>
<div class="jumbotron">
<h1>This is great</h1>
<p>Welcome to templating using EJS</p>
</div>
</main>
<footer>
<%- include('../partials/footer'); %>
</footer>
</body>
</html>

I am facing the some error in my ejs file can someone please assist me?

The error I am facing is as follows:
I have the following code written in server.js file. What am I doing wrong?
var express = require('express');
var app = express();
var instagram = require('instagram-node').instagram();
const ejsLint = require('ejs-lint');
app.use(express.static(__dirname + '/public'));
app.set('view engine', 'ejs');
instagram.use({
client_id:'1063599834134140',
client_secret:'66cbe60a931310beb7a8cf6d4ec7a12f '
});
app.get('/', function(req, res){
//
instagram.media_popular(function(err, medias, remaining, limit)
{
res.render('pages/index', {grams: medias});
});
});
app.listen(8080, function(err)
{
if(err)
{
console.log("Error Occured");
}
else
{
console.log("listening on port 8080");
}
});
And the following is index.ejs
<!DOCTYPE html>
<html>
<head>
<% include ../partials/head %>
<title></title>
</head>
<body class="container">
<header>
<% include ../partials/header %>
</header>
<main>
<div class="row">
<% grams.forEach(function(true){ %>
<div class="instagram-pic col-sm-3">
<a href="<%= gram.link %>" target="_blank">
<img src="<%= gram.images.standard_resolution.url %>" class="img-responsive">
</a>
</div>
<div class="instagram-bar">
<div class="likes">
<span class="glyphicon glyphicon-heart"></span>
<%= gram.likes.count %>
</div>
</div>
<div class="comments">
<span class="glyphicon glyphicon-comment"></span>
<%= gram.comments.count %>
</div>
<% }) %>
</div>
</main>
<footer>
<% include ../partials/footer %>
</footer>
</body>
</html>
Looks to me like your includes are wrong. Using the ejs-lint package that your error message references gives the following:
Unexpected token (4:17) in asdf.ejs
<% include ../partials/head %>
In looking at some ejs docs, the syntax they give for include is:
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 in your case that would be
<%- include('../partials/head') %>
And of course, same for your other includes.
Also for future reference, it would be way better to copy/paste the error text into a code block in your question, instead of linking a screen shot.

EJS: <% vs <%- --> What's the difference

The EJS documentation summarizes the difference between <% and <%- as below:
<% 'Scriptlet' tag, for control-flow, no output
<%= Outputs the value into the template (HTML escaped)
<%- Outputs the unescaped value into the template
However, I noticed that I get the same HTML output whether I use <% or <%-, as below
<%# Include header %>
<% include partials/header %> //Using <%
<h1>This is the home page</h1>
<p>Some content goes here</p>
<%# Include footer %>
<%- include partials/footer %> //using <%-
This is my header.ejs file
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<link rel="stylesheet" type="text/css" href="/app.css">
<title>Demo App</title>
</head>
<body>
I've already checked out the following quesion (EJS: <%= versus <%-) but it didn't explain this behaviour.
<%- and <% tags have different purposes, the first one is simply for unescaped output:
const template = '<%- user %>';
ejs.render(template, { user: 'Alice' }); // renders "Alice"
But let's say there are many users, in this case it may be required to use some flow control structure to iterate over users, this is when <% is used:
const template2 = '<% users.map(user => { %> <%- user -%> <% }) %>';
ejs.render(template, { users: ['Alice', 'Bob'] }); // renders "Alice Bob"
As you can verify, in these examples tags <%- and <% have different behavior and are not interchangeable.
The case you have described with include is pretty special. In my opinion, the expected behavior would be not to output the partials/header (with <%) as it is a simple template (not a flow control).
This is how it works with modern include syntax, i.e if you try to include the header using:
<% include("partials/header") %>
instead of
<% include partials/header %>
you will see that there is no output.
As for the legacy include syntax, it appears that ejs treats it equally inside <% and <%- tags. Should you want to investigate this matter further, inspecting the library source code may be helpful: https://github.com/mde/ejs/blob/master/lib/ejs.js#L713
Or you can simply prefer the new include syntax which appears to provide more consistent behavior.

Resources