Backbone.js model.save() - proper server response - backbone.js

Something seems to be wrong, either my server response or my save function.
In neither case success nor error function of model.save() gets invoked.
My server response:
exports.updateBusinessBannerAd = function(req, res) {
// update banner ad
db.insert(req.body, req.body._id, function(err, data) {
if (err) {
console.log('Update business banner ad: ' + err.message + ' ' + err['status-code']);
res.send(err['status-code'], { header: 'Update banner ad', message: err.message, type: 'error'});
}
else {
res.send(200);
}
});
};
And here my client code:
saveBannerAd: function(self) {
self.model.id = self.model.attributes._id;
self.model.save({
success: function(model, res) {
utils.growl( 'Banner Ad', 'has been updated!', 'info');
self.resetHandler();
},
error: function(model, res) {
console.log(res);
utils.growl(res.header, res.message, res.type);
return;
}
});
},
What am I missing?

Okay, adding { id: self.model.get('id') } as first argument to model.save() fixed my issue.
In this thread
someone suggested setting 'null' as first argument serves as placeholder, but my experience is that this will invoke the error function.

Related

I can't update my contacts

I read some tutorials on MEAN Stack and I'm currently working on one which is almost complete, until I tried my update function. I keep on receiving a 400 message and when i look at the chrome dev tools and under the network tab I read the response which is "_id" is not allowed.
here is the update function
$scope.update = () => {
console.log($scope.contact._id);
$http.put('/api/contacts/updatecontact/' + $scope.contact._id, $scope.contact)
.then(function(data) {
alert('Data was updated Successfully');
refresh();
});
};
here is the api.
app.put('/api/contacts/updatecontact/:id', (req, res) => {
const id = req.params.id;
console.log(req.body.name);
// validation
const { error } = validateInput(req.body);
if (error){
return res.status(400).send(error.details[0].message);
}
const updatedContact = Contact.where({ _id: id });
updatedContact.update({
$set: { name: req.body.name, email: req.body.email
}
}, (err, contact) => {
if(err){
console.log('error occured');
}
res.json(contact);
console.log('contact successfully updated');
});
console.log(updatedContact);
});
hope i can get some help with this.
It seems the node.api is validating the json object that you are passing. Make sure the properties you sent form the client.
Make sure you are not validating or remove the validation on the node.

How to send a message from node.js function to angular controller

I have a variable called message in node.js function now I want to send it to angular controller. How to do this?
api.js
router.post('/pages/auth/forgot-password', function(req,res,next){
var maillist = req.body.email;
async.waterfall([
function(done) {
crypto.randomBytes(20, function(err, buf) {
var token = buf.toString('hex');
done(err, token);
});
},
function(token, done) {
User.findOne({ email : maillist}, function(err, user) {
if (!user){
return done(null, false,{message: 'No account with that email address exists.'});
return res.redirect('/pages/auth/forgot-password');
}
user.resetPasswordToken = token;
user.resetPasswordExpires = Date.now() + 3600000;
user.save(function(err) {
done(err, token, user);
});
});
},
function(token, user, done) {
var mailOptions={
to : maillist,
subject : 'Password Recovery',
text: 'You are receiving this because you (or someone else) have requested the reset of the password for your account.\n\n' +
'Please click on the following link, or paste this into your browser to complete the process:\n\n' +
'http://192.127.0.1:3000/pages/auth/reset-password/' + token + '\n\n' +
'If you did not request this, please ignore this email and your password will remain unchanged.\n'
};
transport.sendMail(mailOptions, function(error, response){
if(error){
return done(null, false,{message: 'An e-mail has been sent to ' + maillist + ' with further instructions.'});
}
transport.close();
});
}
], function(err){
if (err) return next(err);
res.redirect('/pages/auth/forgot-password');
});
return res.json({result:message});
});
I am trying to send like return res.json({result:message}); But it shows an error called message undefined.
Try to do in your last callback
transport.sendMail(mailOptions, function(error, response) {
if (!error) {
var message = {
message: 'An e-mail has been sent to ' + maillist + ' with further instructions.'
};
done(null, message);
}
transport.close();
});
And in final callback
], function(err,result) {
if (err) return next(err);
return res.json({
result: result.message
});
});
Message is not defined in your code
res.json({ result: 'An e-mail has been sent to ' + maillist + ' with further instructions'})
Message is an undefined variable... Either define it or pass a string or better yet use template literals ---> es6!
At the moment u r firing a bunch of async functions but not waiting for any of them to return before you reply to the frontend.
Using Async waterfall in node.js
I assume once yuo finish the work of the async funciton you want to pass a message back?
If not and u just wana send a message...
return res.json({result:'I am a message string....'});
Based on the comment above...
return res.json({result:`An e-mail has been sent to ${maillist} with further instructions`});

put operation in Node.js

For put request:
router.put('/:id', controller.update);
My update method look like this:
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Thing.findById(req.params.id, function (err, thing) {
if (err) { return handleError(res, err); }
if(!thing) { return res.status(404).send('Not Found'); }
var updated = _.merge(thing, req.body);
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.status(200).json(thing);
});
});
};
Making request:
$http.put('/api/things/'+ thing._id, updatedThingObject)
.success(function(update){
console.log("update", update)
})
.error(function(err){
console.log("err", err)
})
It gives connection error on passing the object while making the request in angular.
The error looks like this:
PUT http://localhost:9000/api/things/56c8325b9a0ee7d00d266495
net::ERR_CONNECTION_REFUSED(anonymous function) # angular.js:11442sendReq #
If I take off the updated object, it makes the request just fine but ofcourse nothing gets updated in
that case. What might be wrong here,please?
I figured.
The reason for the functions not being called is that I have a function that is being called repetitively in Node .
var autoCreate = function(){
console.log("THING CREATED AUTOMATICALLY")
var randomNumb=0;
clearTimeout(randomNumb);
randomNumb = (Math.random()* (10-5) + 5).toFixed(0);
console.log("random number", randomNumb)
var randomThing =randomstring({
length: randomNumb,
numeric: false,
letters: true,
special: false
});
console.log("ranfom thing", randomThing)
Thing.create({
name: randomThing,
readByUser: false
}, function(err, thing) {
console.log("THING IS", thing)
//setTimeout(autoCreate, randomNumb * 1000);
});
}
setTimeout(autoCreate, 10*1000);
Since this is running when post/put request is made, I get connection error. How do I handle this to be able to have this function running and be able to make put/post requests as well?

Express + Angular update route: Error: Cannot PUT

I'm trying to update a schema using form, however, both on app.put and app.post (which I've seen as a possible solution) i get
PUT https://myapp-demo.herokuapp.com/api/events/5523da4d97c5000300f6e713 404 (Not Found)
and error from ajax callback
Error: Cannot PUT /api/events/5523da4d97c5000300f6e713
on clientside, I make this request:
$scope.saveEvent = function(id) {
$http.put('../api/events/' + id, $scope.formData)
.success(function (data) {
$scope.events = data;
})
.error(function(data) {
console.log('Error: ' + data);
})
};
In express routes, I do this:
app.put('../api/events/:id', function (req, res){
var user = req.user;
var id = req.params.id;
var update = {
$set: {
title: req.body.title,
description: req.body.description,
}
};
Event.findByIdAndUpdate(id, update, function (err, event) {
if(!event) {
res.statusCode = 404;
return res.send({ error: 'Not found' });
}
console.log("event updated");
Event.find(function(err, events) {
if (err){
res.send(err)
};
res.json(events);
});
});
});
I tried to pass event._id differently, by using req.params.id and passing id with form like req.body.id, it all leads to the same result. I've also read about creating hidden input for helping method-override to override form methods. However, having this didn't help.
<input type="hidden" name="_method" value="put">
<md-button class="md-raised md-primary" ng-click="saveEvent(eventId)">Save</md-button>
UPDATE
Indeed, the initial proble was in my put route. I've found a new problem now. When I try to update it again, I get
Error: Object {error: "Not found"}
It happens even after I refresh page or restart server.
The following is invalid:
app.put('../api/events/:id'...
It needs to be in reference to the namespace, or in your case the root:
app.put('/api/events/:id'...

Backbone.js save always triggers error even on success

I've read several of the other posts about this problem and none of the solutions seem to be working for me. I have the following code in my View:
this.model.set({
username: $('#user-username').val(),
role: $('#user-role').val(),
description: $('#user-description').val()
});
this.model.save({ user_id: this.model.get('user_id')}, {
success: function(user, response) {
console.log('success:', response);
$('.flash-message').text("Success").show();
},
error: function(user, response) {
console.log('error:', response);
$('.flash-message').text(response.error).show();
}
});
and this on my server controller (nodejs running express 3):
UserController.prototype.updateAction = function(req, res) {
if (req.route.method != "put") {
res.send({status: "error", error: "update must be put action and must include values"});
return false;
}
var query = {'user_id': req.params.id};
var user = req.body;
var userRepository = this.userRepository
// delete _id to avoid errors
delete user._id;
userRepository.update(query, user, {}, function(err, updated) {
if ((err) || (!updated)) {
res.send({"status": "error", "error": err});
return false;
}
// send updated user back
util.log('updated user ' + user.user_id);
res.setHeader('Content-Type', 'application/json');
res.status(200);
res.send(JSON.stringify({"status": "success", "updated": updated}));
});
}
On save, my model is saved correctly in the server and I have verified the server response with this. So, as far as I can tell the server is returning status 200, valid JSON, with a valid JSON response header. And yet my backbone model.save function always triggers the error callback. Can anyone please tell me why and how to resolve this?
I am able to get this to work if set the dataType to text like so:
this.model.save({ user_id: this.model.get('user_id')}, {
dataType: "text",
success: function(user, response) {
console.log('success:', response);
$('.flash-message').text("Success").show();
},
error: function(user, response) {
console.log('error:', response);
$('.flash-message').text(response.error).show();
}
});
but doing so does not allow me to get the response back from the server. Instead I get this in the response var:
success: {
"_id": "5133b02062e15ed1d2000001",
}
Backbone expects to get back the model that it sent in its PUT or POST request body.
Instead of:
res.send(JSON.stringify({"status": "success", "updated": updated}));
Try this in your server's response:
res.json(user);
There may be a possibility that your call may have got in state 200 connection established which backbone detects as error, Backbone throws success only when the call is 200OK.
What's your server code? You need to make sure you're sending json back to backbone like so:
//In your express POST route
user.save(function(err) {
if(err){
console.log(err);
return res.json(401);
} else {
console.log('user: ' +user.username + ' saved');
return res.json(200);
}
Then in your backbone view you can check for the response and do what you need:
//some function in your view
this.model.save(this.formValues, {
success: function(model, response, options) {
if (response == 200) {
console.log('success :' + response);
//Do stuff
} else {
console.log('error: '+response);
//etc.
Also note that as per the backbone model documentation:
"save accepts success and error callbacks in the options hash, which will be passed the arguments (model, response, options)"

Resources