Unable to render page after querying model.findOne - node.js

I am using this query and am positively getting a user but unable to render pages.
How do I render the pages inside findOne() without getting errors or warnings?
This is my code:
Company.findOne({'vaccine.name': req_url}, function(err, user){
if(user){
console.log('User Found: ', user.username);
}
return res.render('transaction');
});

This is occurring because there are two return statements and the might already have been sending a render response. Try adding a else statement in the other res.render

Related

When updating element ,which default value false or null, error occurs TypeError: Cannot read property 'exvariable' of null

I am working on nodejs express with mongoose. Every user has such as exvariable which controls permission to have exvariabletext.
My user model schema exvariable and exvariabletext;
exvariable : {type:Boolean,default:false},
exvariabletext:{type:String,default:null}
When I am trying to find user and check if(user.exvariable === false), I am getting an Error such like that TypeError: Cannot read property 'exvariable' of null. So I can't use the default value and update it.
I have tried to change the default value in schema and control in nodejs syntax but couldn't pass the error and I want to understand the logic.
And my code like this;
router.post("/setexvariable",(req,res)=>{
User.findById(req.params.id,(err,user)=>{
if(err){
console.log(err);
req.flash("error","Oops, try again 😔");
res.redirect("back");
}
if(user.exvariable == false){
user.exvariable=true;
user.exvariabletext=req.body.text;
user.save();
req.flash("success","Welcome 😍");
res.redirect("/somewhere",{user:user});
}else{
req.flash("error","You already has a exvariable 😔");
res.redirect("back");
}
});
});
You have to set the id parameter in your route to be able to access it with req.params.id. In your code, req.params.id is undefined, so your query returns null.
You should have something like router.post("/setexvariable/:id", (req, res) => {...}). More on route params in Express's documentation.

How to re-render the same page with additional data

I have two routing functions that have to render the same page but with different data based on the URL.But once I have rendered a page, I am unable to re-render the page, it throws an error
Error: Can't set headers after they are sent.
I have two routes like this
app.post('/abc',function(req,res){
...
res.render('template',{....})
...
});
app.get('/abc/xyz/:params',function(req,res){
...
res.render('template',{...})
...
});
I have a submit button on the /abc page that directs to /abc/xyz/params but it gives me the header error.
Then, I tried to send some data with res.json which I could later handle with AJAX, but once the submit button is pressed the rendered page is lost and hence it only returns a JSON file.
I actually am trying to update a portion of a page without reloading the whole thing,but I am unable to preserve the template once the submit button is pressed.
I even tried the HTML5 History API to change URL without refresh but that even gives me the same error.
This is my whole code
app.post('/login',function(req,res){
dbo.collection("user").find({$and:[{"email":req.body.email},{'password':req.body.password}]}).count().then(function(result){
if(result==1){
dbo.collection("user").findOne({$and:[{"email":req.body.email},{'password':req.body.password}]}, function(err, r) {
req.session.email=req.body.email;
if (err) throw err;
res.render('login', {name:r.name,email: req.body.email,password: req.body.password,status: "Match Found!"});
});
}
else{
console.log('Match not found');
res.render('error_msg', { email: req.body.email,password: req.body.password,status: "Match Not found!"});
}
});
});
app.get('/login/email/:email',function(req,res){
dbo.collection("user").findOne({"email":req.params.email},function(er,r){
if(er)
throw er;
if(r){
res.render('login',{email_search:r.name});
}
else{
res.render('login',{email_search:'No User Found!'});
}
});
});

Express-validator does not catches errors

In node 8.11.1, express 4.16.3 I installed
"express-messages" : "*",
"connect-flash" : "*",
"express-validator" : "*",
"express-session" : "*"
I have a page that gets all articles app.get('/', function(req, res){.... and also has a "New" button, for adding a new article. When hitting New, a pop-up Bootstrap form appears.
I want to check for empty form fields. The HTML form field that I check is
<input type="text" name="name" id="name" class="form-control" />
The form's action goes to
const { check, validationResult } = require('express-validator/check');
app.post('/add', [check('name').exists()],
function(req, res) {
const errors = validationResult(req);
console.log(errors.isEmpty());
if (!errors.isEmpty()) {
req.flash('err', 'errors'); //test
res.redirect('/');
}
else {
pool.connect(function(err, client, done) {
if (err) {
return console.log('db connect error '+ err);
}
client.query('insert into event (name) values($1)',
[req.body.name]);
done();
req.flash('success', 'saved');
res.redirect('/');
}); //pool connect
}//else
});
I am based in this. Whatever I do, the console.log(errors.isEmpty()); is always TRUE, so I end up saving to my DB empty fields. So, the express-validator does not catches errors ?
Also, I am not sure how to pass the errors back in the / route, so the errors can be rendered, this is why I just use req.flash('err', 'errors'); for now. Do I use req.flash like for the success part?
Please help me debug this.Thanks
express-validator maintainer here.
Regarding express-validator letting empty strings come through
check() will create a validator chain for something in the request named name.
It's not assertive of the location of the field, it could be req.query.name or req.body.name, for example.
If you want specifically req.body, then use the other chain creator body().
Then, even if you do have name in req.body, please note that check('name').exists() is not validating its content. It's simply checking it exists, as the name says.
If you want to check that it has some content, whatever that is, you can use check('name').not().isEmpty().
Regarding passing the errors to the redirected page
You can call either errors.array() or errors.mapped() to get the actual errors (please check the Validation Chain API for details).
I haven't used req.flash, so you should test if you can pass an JS object in there, or if you can only pass strings.
If you must use a string, then JSON.stringify/JSON.parse should be your friends to transport your errors.

express-restify-mongoose error propogation

I am having a problem serving up error messages using express-mongoose-restify.
My schema has a hook like
myschema.pre('save', function(next){
// If validation fails
next(new Error('failed to validate model'))
})
For error handling I have (something similar to) the following code
resify.serve(express.Router(), mongoose.model('myschema', {
onError: function(err, req,res,next){
console.log(err)
res.status(400).json(err)
}
})
The output to the console when validation fails is as follows:
{ [Error: failed to validate model] statusCode : 400 }
In my client I have the following (jquery) ajax error handler:
$( document ).ajaxError(function( event, jqxhr, settings, thrownError ) {
console.log(jqxhr)
console.log(thrownError)
});
thrownErorr is equal to "Bad Request" and jqxhr has reseponseText: "{"statusCode" : 400}" similar (but parsed to JS) for the responseJSON. The message failed to validate model is not being sent to the client. I think that I am misunderstanding the type of object that err is in my sever side error handler. Any thoughts? Thanks in advance!
This is one of those cases where writing the question made me think of the right question to ask myself in order to answer it.
The V8 error object that is use by node does not send the additional information such as the stack, message etc when converted to JSON. My problem was solved by reading up on the properties of the Error object here.
In particular using the following handler, the error is successfully relayed to the client
onError : function(err, req, res, next){
res.status(400).json({
message : err.message,
stack : err.stack
})
}

Node Server - res.redirect is using 'PUT' method. Need 'GET'

Using MEAN stack.
I created a mongoose call to update a document in my mongodb collection. That is working, no issue. However when the update is complete I want to "simply" redirect to my '/search' page via server controller.
The redirect works on my other mongoose save call, which is a simple 'POST'.
However when I call redirect after my 'PUT' the redirect is using PUT and not GET, resulting in a 404, that the method PUT /search can't be found. That would be correct!, however I'm not sure why its choosing 'PUT' method. Can I force a 'GET'?
Chrome console log:
PUT http://localhost:3000/search 404 (Not Found)
angular.js:9827 (anonymous function)angular.js:9628 sendReqangular.js:9344 serverRequestangular.js:13189
processQueueangular.js:13205
(anonymous function)angular.js:14401
Scope.$evalangular.js:14217 Scope.$digestangular.js:14506
Scope.$applyangular.js:21440 (anonymous function)angular.js:3014 eventHandler
My express routes are using passport, so all pages that require authentication go through my index.js. (see gist). My mongoose calls calls all go directly from my view or controller to the server via /api/... route.
Hoping this is a quick fix.
My code in a gist.
https://gist.github.com/astemborskim/419d49f0f773fa623a90
Client Controller - call to server to perform update (works)
$scope.updateProduct = function() {
//$scope.edited.inv = $scope.edited.searchSKU;
$scope.edited.inv.SKU = $scope.edited.SKU;
$scope.edited.inv.Product_Name = $scope.edited.Name;
$scope.edited.inv.Product_Description = $scope.edited.Desc;
$scope.edited.inv.Quantity = $scope.edited.quantity;
$scope.edited.inv.Product_Location = $scope.edited.locations;
//console.log('Edited: ' + JSON.stringify($scope.edited.inv));
//console.log('Not Edited: ' + JSON.stringify($scope.prod.currentProd));
var inventory = new Inventory($scope.edited.inv);
//console.log('edited.inv._id: ' + $scope.edited.inv._id);
inventory.$update({id : $scope.edited.inv._id}, inventory, function (err, results){
if(err){};
console.log(results);
});
}
Server Controller - Failing to redirect:
module.exports.editInventory = function(req, res){
Product.update({_id : req.body._id}, req.body, function (err, results){
if(err){
req.flash('message', 'Error Updating Product');
console.log('Error Updating Product: ' + err);
throw err;
}
req.flash('message','Product Updated Successfully!');
res.redirect('/search');
});
};
Let me know if you need additional info.
Try to res.send(200); in server controller and location.reload(); in client's controller callback.

Resources