Why does the wrong EJS tag cause this specific error: SyntaxError: Unexpected token ')' - node.js

Goal: I am trying to understand an error which occurred while trying to render a list of "secrets" (strings passed from JSON objects) in a simple Node app serving EJS files.
Code
app.js
const express = require('express');
const ejs = require('ejs');
const app = express();
app.set('view engine', 'ejs');
app.get("/secrets", (req, res) => {
const user1 = { "username": "jon", "secret": "blue blue blue"};
const user2 = { "username": "paul", "secret": "red red red"};
const users = [user1, user2];
res.render("secrets", {usersWithSecrets: users});
});
app.listen(3000, function() {
console.log("Server started on port 3000.");
});
secrets.ejs
<body>
<html>
<h1>Secrets List:</h1>
<%= usersWithSecrets.forEach((user) => { %>
<p class="secret-text"><%=user.secret%></p>
<%})%>
<hr>
</body>
</html>
Error: SyntaxError: Unexpected token ')' in C:\Users\Owner\Desktop\Sams\scode\Learning\Authentication_and_Redux\code\starting_code\Secrets-Starting_Code\views\secrets.ejs while compiling ejs
I was able to fix the error by changing the 5th line of secrets.ejs to
<% usersWithSecrets.forEach((user) => { %>
but I don't understand why I got the error that I did. I spent a very long time reviewing my code looking for a missing open parenthesis "(" before I even considered that the EJS tags were wrong. Admittedly I am a bit new to EJS, but this error was still very misleading.
Can someone please help me understand why this error was presented instead of an error stating that the EJS tags were wrong?

This happens because to EJS <%= usersWithSecrets.forEach((user) => { %> simply means to insert usersWithSecrets.forEach((user) => { in the <body> element. This is perfectly valid. EJS doesn't assume what you are wanting to do. In other words, that statement is no different than <%= hello world! %> and EJS will happily put that as the text in the <body> tag.
However, when you use the <% %> tag in <% }) %>, it tells EJS that everything here is a script and should be interpreted as javascript. Since there is only a closing bracket and parentheses and no valid javascript earlier to open these, there is now a syntax error. Changing the earlier from an output tag (<%= %>) to a script tag (<% %>) made it a valid javascript script with no error.
In short, just like the javascript interpreter can't assume your intentions, neither can the EJS parser. It couldn't possibly know that you were meaning to start a javascript script and not output usersWithSecrets.forEach((user) => { in the <body> tag. For more information on EJS see the documentation

Related

ExpressJS, EJS: Uncaught SyntaxError: Unexpected token '<' (at file.js 1:1

I have a ExpressJS server with ejs template engine runs a Blockly app and a threejs map in a web page. My problem is that, when I go to /applications/newApp, app.ejs works well but when I go to /applications/:slug (this is a request to load a saved application) the app.ejs crashes with error below:
Uncaught SyntaxError: Unexpected token '<' (at file.js:1:1)
Uncaught SyntaxError: Unexpected token '<' (at anotherFile.js:1:1)
Here is my ejs codes:
<p hidden id="pageName">
<% if(page_name=="savedApp" ) { %>
savedApp
<% } else { %>
newApp
<% } %>
</p>
<p hidden id="slug">
<% if(page_name=="savedApp" ) { %>
<%= slug %>
<% } else { %>
none
<% } %>
</p>
these both calles same file but one works well while another crashes. These are also how server responses;
exports.getNewApp = (req, res) => {
res.render('app', {
page_name: 'newApp',
});
};
exports.loadApplication = async (req, res) => {
try {
res.render('a', {
page_name: 'savedApp',
slug: req.params.slug,
});
} catch (err) {
console.log(err);
res.status(500);
}
};
WHAT I TRIED:
I checked the opened <% %> tags, there is no error in here
I am using public files like that:
app.use(express.static(path.join(__dirname + 'public')));
app.use('/applications', express.static(path.join(__dirname + 'public/blocklyApplication')));
And I also checked following questions:
Express.js, Node.js, EJS - Uncaught SyntaxError: Unexpected token <
SyntaxError: Unexpected token ; while compiling ejs
SyntaxError: Unexpected token ,while compiling ejs
I don't get that, they are both responses same page with common url, one works well other doesnt. What should I check?
I don't know why, after trying some changes in code, adding
app.use(
'/applications/:slug',
express.static(path.join(__dirname + '/public/blocklyApplication'))
);
in my code makes everything work.
EDIT: and also in here Express-js can't GET my static files, why? there is a detailed answer about routed public.

SyntaxError: Unexpected token when compiling ejs

I have been stuck on this error for a while and cannot figure out why I am getting this error.
In my main server file I have set the view engine to ejs :
app.set("view engine", "ejs")
Now, when I am rendering a file from Routes
router.get("/", async function (req, res) {
res.render("main")
}
main.ejs
<h1>Hello :)</h1>
It works fine. But if I try to include partials:
<% include ./partials/header %>
<h1>Hello :)</h1>
<% include ./partials/footer %>
I get the error:
SyntaxError: Unexpected token / in C:\Users\Dacvid\Desktop\Comp Web\views\main.ejs while compiling ejs
My directory structure is shown below:
I think you're using the old syntax of ejs.
Try replacing
<% include ./partials/header %>
by
<%- include("./partials/header") %>

Are there Application scope variables in Node js

I wanted to know are there any application scope variables that can be accessed anywhere in the whole application.
Since I want to add data to my HTML tags using javascript, I need to transfer/get data from the server.js to the index.html
To transfer data from server.js to index.html you don't need to create global variables. You need to use a templating engine: pug, ejs or any other engine.
Just pass the data along with html file in the res.render() function and use templating syntax to display the data at the page.
Router code:
app.get('/', function (req, res) {
res.render('index', { title: 'Hey', message: 'Hello there!'});
});
Pug code:
html
head
title= title //Hey
body
h1= message //Hello there!
ejs code:
<html>
<head> <%= title %> </head>
<body>
<h1> <%= message %> </h1>
</body>
</html>

Render app views per user agent in EJS

I'm working on a Node.js/Express that uses EJS and trying to render certain views on desktop or mobile.
I've added the following middleware to return the user agent in my app.js:
app.use(function(req, res, next) {
res.locals.ua = req.get('User-Agent');
next();
});
Next, if I echo <%= ua %> in my view, I successfully get the user agent, but I'm not sure how to actually check specific agents.
I tried <$ if(ua.match(/iPhone)) { %> as a quick example, but got a syntax error. Any help would be appreciated!
Several errors:
1) You started with a $ inside your embedded script. You should instead use a %.
2) You need to close out your regex with a /.
Something like this:
<% if(ua.match(/Intel/)) { %>
<%= ua %>
<% } %>

How does one use ejs with node-webkit

in package.json
{
"name": "_dubs",
"version": "0.0.0",
"description": "GAME",
"main": "views/index.ejs",
...
the app gives me this error "SyntaxError: unexpected token <"
Which I assume to be an issue due to ejs! (embedded js)
Any idea on how I can get around this?
You can't use anything other than pure html5 as your main file as far as node-webkit is concerned. You would have to use the ejs module to first compile the content you want to appear in your document, then place said content into the document as you wish.
Here's an example that might help:
index.html
<html>
<head>
<script>
var fs = require('fs');
var ejs = require('ejs');
fs.readFile('./index.ejs', function(err, data){
if(err){
document.body.innerHTML = err.toString();
return;
}
var template = ejs.compile(data.toString());
document.body.innerHTML = template({ name: 'world' });
});
</script>
</head>
<body>
Not yet rendered...
</body>
</html>
index.ejs
<div>hello, <%= name %>!</div>
Make sure that you have ejs installed as a dependency through npm, then when you run this, your body should then contain:
<div>hello, world!</div>

Resources