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.
Related
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
I want to send a message variable that says something like succeeded or failed wihtout the use of passport or sessions.
When it fails I can just do this:
res.status(401).render('register', {
message: 'Your username/email or password is incorrect.'
})
So I was thinking this was possible:
res.redirect('/');
res.render('', { message: 'Login success.'});
But it turns out it isn't:
Error: Cannot set headers after they are sent to the client
Are there any simple sollutions?
I tried making a router.get('/message/redirect :route') but I realised I ran into the same problem there too.
You are redirecting before rendering. So the render method can't send headers because you have already redirected them. You need to call either redirect or render, not both at once. you can do it like this.
res.render('/', { message: 'Login success.'});
remove this line
res.redirect('/');
In your EJS file just call <%= message %> to access the message. There is a better way of dealing with confirmation/error messages. Use Flash.
npm install express-flash
Then before rendering, call the flash. Flash takes two arguments, a name of the message and the message itself, Like this
req.flash("MessageName", "Login success");
res.redirect(pathName);
Make sure to use flash
const flash = require('express-flash');
app = express();
app.use(flash());
app.use((req, res, next) => {
res.locals.MessageName= req.flash("MessageName");
next();
});
To access the message in EJS file just call <%= MessageName %>
Here is sample from my code:
In the server file:
req.flash("error", "Something went wrong");
res.redirect('back');
In the EJS file:
<div class="flash">
<% if(error && error.length > 0){ %>
<div class="flash_error">
<h1 class="flash_error--text"><%= error %></h1>
</div>
<% } %>
</div>
Read this for more information
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") %>
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 %>
<% } %>
I currently have an express/node application I want to test, and but responses that it gives are in the form of req.flash('warn', 'message goes here');
Unfortunately, the documentation on express.js does not describe how this message travels to the client very thoroughly.
I know expresso has an assert.response() function that tests response objects. I was wondering where the flash message goes, and how I can test it in a similar way (or if it's not possible, and I should be sending everything through the response object).
i don't think this is supposed to work like that. you can't just use req.flash()as your only way to respond to a request.
it's more like an easy way to flash messages to the user on your normal templates - e.g. after inserting/creating an article you can either say:
req.flash('error', 'could not insert because .... ');
or
req.flash('info', 'article added successfully!');
for my last project i then added two dynamic helpers to my app:
app.dynamicHelpers({
info: function (req, res) {
return req.flash('info');
},
error: function (req, res) {
return req.flash('error');
}
});
so that i can just say sth like this in my view:
<% if (info !== undefined && info != "") { %>
<div class="infoBubble">
<%= info %>
</div>
<% } %>
<% if (error !== undefined && error != "") { %>
<div class="errorBubble">
<strong>Fehler</strong>: <%= error %>
</div>
<% } %>
result looks like this: