express-validator error message attributes and location - node.js

I am using expressJS, Node and Handlebars.
In my post function I have the following:
routes.js
req.assert("referenceNumber", "Enter ...").notEmpty();
req.assert("yourPostcode", "Enter ...").notEmpty();
var errors = req.validationErrors(true);
if (errors) {
res.render('<page>/index', {
title: "<title>",
errors: errors
});
} else {
// Redirection
}
index.hbs
{{#if errors}}
<ul>
{{#each errors}}
<li>{{this.msg}}</li>
{{/each}}
</ul>
{{/if}}
This outputs a list of errors on submission which is great. The problem is I need the error message located next to the form field as well as.
So ideally I can target each error by name e.g. "referenceNumber", "yourPostcode".
I have thought about maybe having a variable inside the routes.js like so:
if (errors) {
res.render('<page>/index', {
title: "<title>",
referenceNumber: <something>,
yourPostcode: <something>
});
And perhaps be able to do something funky this way.
It would also be very good associating an id with each error message to act as an anchor link to each error form field.
Totally stumped with this one, and would really appreciate some help.

Related

Not being able to delete an item from to-do list using Item.removeOne( ) or Item.findByIdAndRemove( ) methods of mongoose in NodeJS

I am making a to-do list using mongodb,node.js,express and EJS. The part where I am stuck is I am not being able to delete and item from the list and the database. The idea is that on clicking a checkbox, the item beside will be deleted. Here is a layout for the same,
[https://i.stack.imgur.com/83gMW.png][1]
I made the necessary changes in my EJS file to create a "/delete" route as given below :
<%for(var i=0;i<taskslist.length;i++){%>
<form action="/delete" method="POST">
<div class="item">
<input type="checkbox" name="checkitem" value="<%= taskslist[i]._id %> " onChange="this.form.submit()">
<p><%= taskslist[i].activity %> </p>
</div>
</form>
<%}%>
In my app.js folder, I also made the necessary changes by using findByIdAndRemove( ) method for mongoose :
app.post("/delete", function (req, res) {
const delitem = req.body.checkitem;
Item.findByIdAndRemove(delitem, function (err) {
if (err) {
console.log("Error");
} else {
console.log("Succesfully deleted" + delitem);
res.redirect("/");
}
});
console.log(delitem);
});
However, the item is not getting deleted from the database and an error is showing in terminal, even though the console.log(delitem) is working and returning the id of the item whose checkbox is selected.
I am also giving a screenshot of the output I am getting at the terminal:
[https://i.stack.imgur.com/hGEkn.png][1]
All the methods related to adding items and creating database are working. I don't understand where the error is. Please help me out with this.

Redirect and render template with new variables

I will show my code first in order to be clear.
router.get("/add", (req, res)=>{
res.render("user/add.ejs");
});
router.put("/add/pi", (req, res)=>{
if(condition){
//do something
}else{
res.redirect("/user/add");
//res.render("user/add.ejs", {error: "At least one field should be filled in order to submit the form", type: "form error","location": "form-container"});
}
});
Ejs:
<% if(error){ %>
<small id="personalinformationError" class="form-text text-danger"><%= error %></small>
<% }%>
I want to be able to render the ejs template with the object in the render() in the comment. I tried to render it like in the comment without redirect() and it shows an error whenever I mention the variable name. The error goes like variable is not defined.
Thank you in advance.

Data passed to Handlebars not showing

I want to display items from the database which I already log the result to the console. The console displays the result. but handlebars not displaying data.
This is controller
exports.createCategory = function(req, res, next){
knex('product_category')
.select()
.then(function(errors, result){
res.render('administration/category', { result, errors });
});
}
This is my router
router.get('/category', adminControllers.createCategory);
and this is my handlebar
<div class="col-md-4 col-lg-4">
{{#each result}}
<h1>{{category_name}}</h1>
{{/each}}
</div>
Just do debugging 101.
Add debug prints and check that you get correct data from DB and that it even executes.
Add to template some field to show you error too. Now if error is returned from query, nothing is shown.
Also add some static test attribute that you pass to template and print it to make sure that you are using handlebars template correctly.
I later got it.
Its the knex query.
after studying the knex docs and some online resources, I discovered I can also do this
knex('table').then(function(result)){
res.render('/', {result});
}
but I don't why this didn't work
knex('table').select().then(function(result)){
res.render('/', {result});
}

Express JS does not perform delete

PUGJS script
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
My ExpressJS code
router.post('/delete', function(req, res, next) {
var id = req.params("i");
console.log("i am 0")
MongoClient.connect(url, function(err, db) {
console.log("i am 1")
db.collection('books', function(err, book) {
db.collection.deleteOne( {_id: new mongodb.ObjectID(id)} );
console.log("i am 2")
if (err) {
throw err;
} else {
db.close();
res.redirect('/');
}
});
});
});
Trying to perform a delete request but it does not even print ("i am 0")
can not determine what's broken with the code
NPM response POST /delete 404 7.247 ms - 1202
When you see a 404 the root cause is definitely how you set up the routing. This code would be successfully called if it is in app.js/server.js (or whatever your root express file is), but a 404 means that you have placed it in a secondary file and are using another path in there somewhere.
With that said, you also have an issue with how your route is defined if you want to read a route parameter (which is what the first line of your route handler tries to do).
router.post('/delete/:i', function...
The form itself isn't passing any id though through name (or id). You could either pass the id through the url called:
action= "/delete?id=" + id
...and read this in your route handler using req.query.id or you could insert a hidden input in the form and read it using req.body.id.
Also, the form name attribute has been deprecated and should be replaced with id.
Then, it's important to note that pug is highly dependent on indentation. Your code as pasted will generate an empty form and a separate input field.
This:
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
Generates this HTML:
<form id="form1" action="/delete" method="POST"></form>
<input type="submit" name="itemId" value="delete">
If you change the pug template to this (note the two additional spaces on the input line):
form(id="form1" action="/delete" method="POST")
input(type="submit",name=+item['id'] value="delete")
You will get this, which should work as expected:
<form id="form1" action="/delete" method="POST">
<input type="submit" name="itemId" value="delete">
</form>
Then, there's the problem in your delete function where you're missing a callback.
db.collection.deleteOne( {_id: new mongodb.ObjectID(id)} );
You need to either add a promise or callback here otherwise your code will move straight to close the connection.

Unable to display flash message in view with ejs template

I am a newbie in NodeJS. I have a problem that I am unable to show flash message in my view.
Here is my Controller,
index : function(req, res){
res.locals.flash = _.clone(req.session.flash);
res.locals.layout = false;
res.view('login');
},
login : function(req, res){
....
if(!admin){
req.session.flash = {
err : 'User is not found.' // My flash message
}
res.locals.layout = false;
res.redirect('login');
return;
}
.....
}
Here is my view,
<% if(flash && flash.err) { %>
<div class="alert alert-danger">
<% JSON.stringify(flash.err) %>
</div>
<% } %>
When login is false, it show only an empty alert box.
And I have a second problem. When I refresh page, The alert box isn't disappeared.
Could someone help me please.
Thanks a lot.
The alert box keeps on appearing because the req.session.flash object persists the session, so you need to null that out once it's used, or you can just simply use req.flash(), which does that for you. So change your index method to something like this:
index: function(req, res) {
// req.flash() returns the contents of req.session.flash and flushes it
// so it doesn't appear on next page load. No need to clone.
res.locals.flash = req.flash();
res.locals.layout = false;
res.view('login');
},
Now, onto the second problem. The error messages aren't appearing because you aren't using the proper EJS syntax to output escaped values into the view. All you need to do is change your code to this:
<% if(flash && flash.err) { %>
<div class="alert alert-danger">
// Change <% to <%=
<%= flash.err %>
</div>
<% } %>
No need to JSON.stringify, unless you like the quotes. Notice that I changed the <% to <%=, which in EJS means "escape this and output it". It's not template HTML or anything like that, so it's okay to escape it anyway.

Resources