AJAX POST request never completes. Data posts to server - ajax

I am sending a post request via AJAX. The data successfully posts but the AJAX call never completes. Backbone on the front; Node on the back. I am including the save function from my backbone view and the express route.
save: function(event) {
event.preventDefault();
console.log( 'You signed up for ' + this.model.get('name'));
var name = this.model.get('name');
var courseDay = this.model.get('courseDay');
var time = this.model.get('time');
var location = this.model.get('location');
jQuery.post("/test/signups", {
"name" : name,
"courseDay" : courseDay,
"time" : time,
"location" : location,
}, function (data, textStatus, jqXHR) {
console.log("Post response:");
console.dir(data);
console.log(textStatus);
console.dir(jqXHR);
});
}
Route:
app.post('/test/signups', isLoggedIn, function (req, res){
User.findOne({'_id': req.user.id }, function(err, user) {
if (err)
return done(err);
if (user) {
user.signup.name = req.body.name;
user.signup.courseDay = req.body.courseDay;
user.signup.time = req.body.time;
user.signup.location = req.body.location;
user.signup.modified = req.body.modified;
user.update({$push: { "signup" :
{ name: user.signup.name,
courseDay: user.signup.courseDay,
time: user.signup.time,
location: user.signup.location,
modified: user.signup.modified
}
}},{safe:true, upsert:true},function(err){
if(err){
console.log(err);
} else {
console.log("Successfully added" + user.signup);
}
});
}
});
});

Your server side code needs to send a response. Try something like below. Note I try to cover all cases of an error, user not found, and user found.
app.post('/test/signups', isLoggedIn, function (req, res){
User.findOne({'_id': req.user.id }, function(err, user) {
if (err) {
return res.status(500).send(err);
}
if (user) {
user.signup.name = req.body.name;
user.signup.courseDay = req.body.courseDay;
user.signup.time = req.body.time;
user.signup.location = req.body.location;
user.signup.modified = req.body.modified;
user.update({$push: { "signup" :
{ name: user.signup.name,
courseDay: user.signup.courseDay,
time: user.signup.time,
location: user.signup.location,
modified: user.signup.modified
}
}},{safe:true, upsert:true},function(err){
if(err){
return res.status(500).send(err);
}
console.log("Successfully added" + user.signup);
res.send(user);
});
} else {
res.status(404).send();
}
});
});

Related

AJAX error return ModelState Error

On my Create page I am using ajax and calling my api controller when creating a person:
<script>
$(document).ready(function() {
var newUrl = '#Url.Action("Index", "PersonInformations")';
var settings = {};
settings.baseUri = '#Request.ApplicationPath';
var infoGetUrl = "";
if (settings.baseUri === "/ProjectNameOnServer") {
infoGetUrl = settings.baseUri + "/api/personinformations/";
} else {
infoGetUrl = settings.baseUri + "api/personinformations/";
}
$("#Create-Btn").on("click",
function(e) {
$("form").validate({
submitHandler: function () {
e.preventDefault();
$.ajax({
method: "POST",
url: infoGetUrl,
data: $("form").serialize(),
success: function () {
toastr.options = {
onHidden: function () {
window.location.href = newUrl;
},
timeOut: 3000
}
toastr.success("Individual successfully created.");
},
error: function (jqXHR, textStatus, errorThrown) {
var status = capitalizeFirstLetter(textStatus);
var error = $.parseJSON(jqXHR.responseText);
//console.log(jqXHR.responseText);
toastr.error(status + " - " + error.message);
}
});
}
});
});
function capitalizeFirstLetter(string) {
return string.charAt(0).toUpperCase() + string.slice(1);
}
});
</script>
Here is the method in my PersonInformations API controller:
[ResponseType(typeof(PersonInformation))]
public IHttpActionResult PostPersonInformation(PersonInformation personInformation)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var lstOfPersons = db.PersonInformations.Where(x => x.deleted == false).ToList();
if (lstOfPersons.Any(
x =>
x.FirstName == personInformation.FirstName && x.LastName == personInformation.LastName &&
x.AId == personInformation.AgencyId && x.ID != personInformation.ID))
{
ModelState.AddModelError("", "This person already exists!");
return BadRequest(ModelState);
}
if (
lstOfPersons.Any(
x => x.Email.ToLower() == personInformation.Email.ToLower() && x.ID != personInformation.ID))
{
ModelState.AddModelError(personInformation.Email, "This email already exists!");
return BadRequest(ModelState);
}
personInformation.FirstName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(personInformation.FirstName);
personInformation.LastName = CultureInfo.CurrentCulture.TextInfo.ToTitleCase(personInformation.LastName);
db.PersonInformation.Add(personInformation);
db.SaveChanges();
return CreatedAtRoute("DefaultApi", new { id = personInformation.ID }, personInformation);
}
Now when I test this and purposely enter an email that already exists, the ajax request errors out but returns the message:
Error - The Request is invalid
but when I use console.log(jqXHR.responseText)
I get this:
Create
{
"$id": "1",
"message": "The request is invalid.",
"modelState": {
"$id": "2",
"test#test.com": [
"This email already exists!"
]
}
}
How do I get the "This email already exists!" as the error message?
I just figured this out. I know that the modelState was an array type, and the 2nd value was the actual email address entered.
So I edited my button.click event to this:
$("#Create-Btn").on("click",
function(e) {
$("form").validate({
submitHandler: function () {
e.preventDefault();
var emailValue = $("#Email").val();
$.ajax({
method: "POST",
url: infoGetUrl,
data: $("form").serialize(),
success: function () {
toastr.options = {
onHidden: function () {
window.location.href = newUrl;
},
timeOut: 3000
}
toastr.success("Individual successfully created.");
},
error: function (jqXHR, textStatus, errorThrown) {
var status = capitalizeFirstLetter(textStatus);
var error = $.parseJSON(jqXHR.responseText);
toastr.error(status + " - " + error.modelState[emailValue]);
}
});
}
});
});
Find the error message via array bracket notation along with getting the actual value of the email trying to be submitted did the trick.

Does Vue.JS work with AJAX http calls?

I am trying to do the following from my HTML:
var vm = new Vue({
el: '#loginContent',
data: {
main_message: 'Login',
isLoggedIn: false,
loginError: '',
loginButton:'Login'
},
methods: {
onLogin: function() {
//this.$set(loginSubmit, 'Logging In...');
var data = {
email: $('#email').val(),
password: $('#password').val(),
};
$.ajax({
url: '/api/login',
data: data,
method: 'POST'
}).then(function (response) {
if(response.error) {
console.err("There was an error " + response.error);
this.loginError = 'Error';
} else {
//$('#loginBlock').attr("hidden",true);
console.log(response.user);
if(response.user) {
this.isLoggedIn = true;
} else {
this.loginError = 'User not found';
}
}
}).catch(function (err) {
console.error(err);
});
}
}
});
Basically user presses the login button, onLogin method is called that sends a post to my API. The post is working fine and I do get the response back in the .then() promise.
But, trying to do things like this.isLoggedIn = true; does not update my DOM with what I am expecting the HTML to do when the user logs in.
Could be that I am in some sort of background thread (sorry, mobile developer here) when I get the response in the promise and it can't find the "vm" instance?
Thanks
It is probably happening because your this is not pointing to correct scope, scope of this changes inside an $.ajax call, so you just have to do something like following:
methods: {
onLogin: function() {
//this.$set(loginSubmit, 'Logging In...');
var data = {
email: $('#email').val(),
password: $('#password').val(),
};
var that = this
$.ajax({
url: '/api/login',
data: data,
method: 'POST'
}).then(function (response) {
if(response.error) {
console.err("There was an error " + response.error);
that.loginError = 'Error';
} else {
//$('#loginBlock').attr("hidden",true);
console.log(response.user);
if(response.user) {
that.isLoggedIn = true;
} else {
that.loginError = 'User not found';
}
}
}).catch(function (err) {
console.error(err);
});
}
}
I would propose another method use ES6 Arrow Functions like '=>'. It is simple and do not need extra variable.Like following:
$.ajax({
url: '/api/login',
data: data,
method: 'POST'
}).then((response) => {
if(response.error) {
console.err("There was an error " + response.error);
this.loginError = 'Error';
} else {
//$('#loginBlock').attr("hidden",true);
console.log(response.user);
if(response.user) {
this.isLoggedIn = true;
} else {
this.loginError = 'User not found';
}
}
}).catch(function (err) {
console.error(err);
});
You might want to take a look at axios. I used $.ajax and got it working, but found axios and prefer axios over the ajax library.

how to access to filename in my requst block in multer

I Need Access to file name in my request body because i want store in my db but i dont know handle that , this is my code :
var storage = multer.diskStorage({
destination: function (req, file, callback) {
var name = 'public/images/' + Math.floor((Math.random() * 10675712320) + 1);
fs.mkdir(name, (err)=> {
if (err) {
console.log(err);
} else {
** Im want pass name variable**
callback(null, name);
}
});
},
filename: function (req, file, callback) {
callback(null, file.originalname);
}
});
var upload = multer({storage: storage}).single('userPhoto');
app.post('/api/photo', function (req, res) {
***upload(req, res, function (data) {
I need access to file name here because i want store in my db***
console.log(data);
res.end("File is uploaded");
});
});
Im try this way but not working :
fs.mkdir(name, (err)=> {
if (err) {
console.log(err);
} else {
callback(name, name);
}
});
you can access to path from req.file.path like this :
var upload = multer({storage: storage}).single('userPhoto');
app.post('/api/photo', function (req, res) {
upload(req, res, function (data) {
console.log(req.file.path);
res.end("File is uploaded");
});
});

Can not connect with API , so couldn't retrieve post from db?

I got problem while I move into https://github.com/DaftMonk/generator-angular-fullstack.
Before my project was working. Here is code for frontend and backend part related to comment.
I am getting all time error 404. I don't know why I cannot find following path.
POST http://localhost:9000/api/providers/554a1dba53d9ca8c2a2a31ff/posts/554b1726f1116e00256e3d82/comments 404 (Not Found)
I am struggling couple of days to discover which part of my code have problem but I couldn't realize that.
server side
in comment.controller
// Creates a new comment in the DB.
exports.create = function(req, res) {
console.log('i ma inside api');
Post.findById(req.originalUrl.split('/')[3], function (err, post) { //here can not find post at all.
if (err) {
return handleError(res, err);
}
if (!post) {
return res.status(404).send('Post not found');
}
Comment.create(req.body, function (err, comment) {
if (err) {
return handleError(res, err);
}
post.comments.push(comment.id);
post.save(function (err) {
if (err) return handleError(res, err);
return res.status(201).json(comment);
});
});
});
};
route.js
app.use('/api/providers/:providerId/posts/:postId/comments', require('./api/provider/post/comment'));
index.js
var controller = require('./comment.controller.js');
var router = express.Router();
router.get('/', controller.index);
router.get('/:id', controller.show);
router.post('/', controller.create);
router.put('/:id', controller.update);
router.patch('/:id', controller.update);
router.delete('/:id', controller.destroy);
router.put('/:id/upvote', controller.upvote);
in client side:
factory:
//create new comment for post
ob.createComment = function(providerId, postId,comment) {
console.log('i am inside factory');
return $http.post('/api/providers/'+ providerId + '/posts/' + postId + '/comments' ,comment, {
headers: {Authorization: 'Bearer '+Auth.getToken()}
}).success(function(data){
_.forEach(ob.provider.posts,function(value,index){
if(value._id === post._id){
ob.posts[index].comments.push(data);
}
})
ob.current.comments.push(data)
// ob.provider1._id.posts.push(data);
});
};
in my controller
$scope.addComment = function(){
// if(!$scope.title || $scope.title === '') { return; }
if(!$scope.body || $scope.body === '') { return; }
console.log('$stateParams',$stateParams);
providers.createComment($stateParams.providerId, $stateParams.postId,{
//title: $scope.title,
body: $scope.body
});
$scope.body = '';
$scope.title = '';
};
This is my model in whole the project.

Parse - Get object from pointer on beforeSave?

I have an Offer object that I send to the server, when this offer is about to be created I need to send a push notification to the user. Offer has a pointer to User an the field is called "to".
How can I fetch an object from a pointer?
Parse.Cloud.beforeSave("Request", function(request, response) {
var userQuery = new Parse.Query("User")
userQuery.get(request.object.get("to").id, {
success: function (user) {
console.log("user: ", user);
var installationQuery = new Parse.Query("Installation");
installationQuery.equalTo("user", user);
Parse.Push.send({
where : installationQuery,
data : {
alert : "HEllo"
},
success : function() {
},
error : function() {
console.log("error finding installation: " + error);
}
});
},
error : function (error) {
console.log("ERRRRRRRRRR");
}
});
response.success();
});
To answer your question directly, you can use Parse.Query.get() or Parse.Object.fetch() to retrieve the object.
I'm assuming that the problem you see is that the object saves but the push notification isn't happening. The cause is that you're not waiting for the get() to complete before calling response.success() and returning.
Here's a couple ways to reconcile that:
Your existing code but with response.success() moved up:
Parse.Cloud.beforeSave("Request", function(request, response) {
var userQuery = new Parse.Query("User")
userQuery.get(request.object.get("to").id, {
success: function (user) {
console.log("user: ", user);
var installationQuery = new Parse.Query("Installation");
installationQuery.equalTo("user", user);
Parse.Push.send({
where : installationQuery,
data : {
alert : "HEllo"
},
success : function() {
response.success();
},
error : function() {
console.log("error finding installation: " + error);
}
});
},
error : function (error) {
console.log("ERRRRRRRRRR");
}
});
});
Simplified with Promises
Parse.Cloud.beforeSave("Request", function(request, response) {
request.object.get("to").fetch().then(function(user) {
var installationQuery = new Parse.Query("Installation");
installationQuery.equalTo("user", user);
return Parse.Push.send({
where : installationQuery,
data : {
alert : "HEllo"
}
});
}).then(function() {
response.success();
}, response.error);
});
Further simplified. If you're not using the data within user, you shouldn't need to fetch it just to pass a pointer to a query.
Parse.Cloud.beforeSave("Request", function(request, response) {
var installationQuery = new Parse.Query("Installation");
installationQuery.equalTo("user", request.object.get("to"));
return Parse.Push.send({
where : installationQuery,
data : {
alert : "HEllo"
}
}).then(function() {
response.success();
}, response.error);
});

Resources