Updating database with node.js and angular - angularjs

I have an app which posts, gets and deletes data and I would like to add 'update' functionality as well but I can't figure it out..
I have a node.js server which has such api:
app.get('/api/feedbacks', function(req, res) {
// use mongoose to get all feedbacks in the database
getfeedbacks(res);
});
// create feedback and send back all feedback after creation
app.post('/api/feedbacks', function(req, res) {
// create a feedback, information comes from AJAX request from Angular
FeedBack.create(req.body, function(err, feedback) {
if (err)
res.send(err);
// get and return all the feedbacks after you create another
getfeedbacks(res);
});
});
// delete a feedback
app.delete('/api/feedbacks/:feedback_id', function(req, res) {
FeedBack.remove({
_id : req.params.feedback_id
}, function(err, feedback) {
if (err)
res.send(err);
getfeedbacks(res);
});
});
and such angular service which speaks to node api:
service.factory('FeedBacks', ['$http',function($http) {
return {
create : function(feedBackData) {
return $http.post('/api/feedbacks', feedBackData);
},
get : function() {
return $http.get('/api/feedbacks');
},
delete : function(id) {
return $http.delete('/api/feedbacks/' + id);
}
}
}]);
That way I can post, get and delete data.
My goal is to add also update function.
What I have tried on node:
// update a feedback
app.put('/api/feedbacks/:feedback_id', function(req, res) {
// edit a feedback, information comes from AJAX request from Angular
FeedBack.put(req.body, function(err, feedback) {
if (err)
res.send(err);
// get and return all the feedbacks after you edit one
getfeedbacks(res);
});
});
on Angular service:
update: function(editFeedId, editedFeed){
return $http.put('/api/feedbacks/' + editFeedId, editedFeed);
}
controller looks like:
$scope.editFeed = function(id) {
$scope.editFeedId = id;
$scope.editedFeed = 'replace this txt'
FeedBacks.update($scope.editFeedId, $scope.editedFeed)
// if successful creation, call our get function to get all the new
feedBacks
.success(function(data) {
console.log('updated');
$scope.feedbacks = data;
});
};
I get 500 error as I execute editFeed(). I couldn't figure out to configure that! Where do I do wrong? Any Tips?
Thanks a lot in advance!

I'm assuming you're using Mongo here, in which case your update statement is incorrect.
It should be something like:
app.put('/api/feedbacks/:feedback_id', function(req, res) {
FeedBack.update({_id: req.params.feedback_id}, req.body, function(err, feedback) {
if (err)
res.send(err);
// get and return all the feedbacks after you edit one
getfeedbacks(res);
});
});

Related

How to send a request from express to mongodb to delete multiple record from collections

Delete multiple record from mongodb collections using angular and express.
How I can send array of ids from express to mongodb.
Here is code for deleting single todo from mongodb in express
app.delete('/api/todos/:id', function(req,res){
Todos.remove({
_id: req.params.id
}, function(err, todos){
if(err)
res.send(err);
Todos.find(function(err, todos){
if(err)
res.send(err)
res.json(todos);
});
});
});
angular controller code
$scope.deleteTodo = function(id){
$http.delete('/api/todos/'+ id).then(function(response){
var data = response.data;
$scope.todos = data;
});
}
Easy approach is to re-use your route by just passing comma-separated list of IDs e.g. /api/todos/id1,id2,id3.
app.delete('/api/todos/:ids', function (req, res) {
Todos.remove({
// convert string of IDs to array of IDs
_id: { $in: req.params.ids.split(',') }
}, function (err) {
if (err) return res.send(err);
Todos.find({}, function (err, todos) {
if (err) return res.send(err)
res.json(todos);
});
});
});
How I can send array of ids from express to mongodb.
In this example I show you how to make an array from the parameter and using underscore each loop we iterate over the array of ids to delete one by one.
app.delete('/api/todos/:id', function(req,res){
try{ //:id can be a list of ids separated by ','
var deleteID = req.params.id.split(','); //array is made
// Temp. Error Log
var errorCount = 0; var errorLog = '[ERROR LOG]\n';
// Delete each ID
_.each(deleteID,function(this_id,index){
Todos.remove({id:this_id},function(err,todos){
//errors occuring while deleting, stored into temp log
if(err){errorCount++;errorLog+="\n["+index+"]\n"+err;}
});
});
// Check if any errors happened
if(errorCount!=0){ // RETURN ERRORS :
res.send(errorLog);
}else{ // NO ERRORS :
Todos.find(function(err, todos){
if(err){res.send(err);}
else{res.json(todos);}
});
}
}catch(e){res.end(); console.log(e);}
});

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?

update and put routes responding error 500

I'm having difficulty setting up put and delete roots in a project the get and post methods at the same url are working fine. Currently, I'm getting an error 500 and a degree of debugging makes me think that the error is in the $http call. For the put route
factory.update(question) is called:
o.update = function(question) {
console.log('update was called')
return $http.put('/questions', question).success(function(data){
o.questions.push(data);
});
};
Which should call the put route in the express routes file:
/*UPDATE question*/
router.put('/questions', function(req, res, next){
console.log('made it to index.js');
var question = req.body;
question.title = req.body.title;
question.type = req.body.type;
question.key = req.body.key;
question.options = req.body.options;
question.save(function(err){
if (err) {
return res.status(400).send({
message: getErrorMessage(err)
});
} else {
res.json(article);
}
});
});
For the delete route factory.remove(question) is called:
o.remove = function(question) {
return $http.delete('/questions', question).success(function(data){
o.questions.push(data);
});
}
Which should in turn call the delete route in the express routes file:
/*DELETE question*/
router.delete('/questions', function(req, res, next){
var question = req.body;
article.remove(function(err) {
if (err) {
return res.status(400).send({
message: getErrorMessage(err)
});
} else {
res.json(article);
}
});
});
It seems that in both cases the methods in the express routes file are never called which is strange because nearly identical $http requests work elsewhere in the code just fine. How do access my api?

NodeJs + ExpressJs app routing odd behavior

I am learning ExpressJS. So far I have setup a simple todo app with user authentication using PassportJS. I use Mongoose for repository. There is nothing in the web to explain the odd behavior that I'm seeing with my route setup.
Scenario:
When I hit get /passport it will direct to the passport page
(login/signup)
When I hit get /aslkdjf it will direct to the passport page if
user is not logged in, else it will direct to the file
/public/index.html)
When I hit get / it should direct to the passport page if user
is not logged in, but it goes to /public/index.html instead and
my todo app would fail as req.user.username under /api/todos is
undefiend
Strangely, when I remove the router.get('/*', ... configuration, my app would still go to public/index.html, when I hit base path '/', but not when I hit '/asdfa'.
...
function loggedIn(req, res, next) {
if (req.user) {
next();
} else {
res.redirect('/passport');
}
}
var router = express.Router();
// passport ----------------------------------------------------------------
// get passport page
router.get('/passport', notLoggedIn, function(req, res) {
res.sendfile('./public/passport.html');
});
// post login
router.post('/login', passport.authenticate('login', {
successRedirect: '/',
failureRedirect: '/passport',
failureFlash: true
}));
// post registration
router.post('/signup', passport.authenticate('signup', {
successRedirect: '/',
failureRedirect: '/passport',
failureFlash: true
}));
router.get('/logout', function(req, res) {
req.session.destroy();
req.logout();
res.redirect('/');
});
// api ---------------------------------------------------------------------
// get all todos
router.get('/api/todos', function(req, res) {
// use mongoose to get all todos in the database
Todo.find({owner: req.user.username}, function(err, todos) {
// if there is an error retrieving, send the error. nothing after res.send(err) will execute
if (err)
res.send(err)
res.json(todos); // return all todos in JSON format
});
});
// create todo and send back all todos after creation
router.post('/api/todos', function(req, res) {
// create a todo, information comes from AJAX request from Angular
Todo.create({
owner: req.user.username,
text : req.body.text,
done : false
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find({owner: req.user.username}, function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
// delete a todo
router.delete('/api/todos/:todo_id', function(req, res) {
Todo.remove({
_id : req.params.todo_id
}, function(err, todo) {
if (err)
res.send(err);
// get and return all the todos after you create another
Todo.find({owner: req.user.username}, function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
// application -------------------------------------------------------------
router.all('*', loggedIn);
router.get('/*', function(req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});
app.use('/', router);
app.listen(3000);
console.log("App listening on port 3000");
Can someone explain to me what is going on? All I want to achieve is to make the app re-route user to the login page when they are not logged in and they go to www.myapp.com/
So apparently the problem is that HTML defaults to finding an index.html file in any folder within the root. When I change the html file to something else like abc.html the problem is solved. Seems like a bug to me.

NodeJS - Cannot set headers after they are sent - Multiple Calls

I'm trying to write an app that find a city in a MongoDB collection and uses the latitude and longitude it returns to find all zip codes within a certain distance. It seems to work, but the problem is that I'm getting an error that I can't set headers after they've already been sent. However, I've separated the to routes into different requests I don't understand why I'm still getting this error. What is the best way to make multiple calls to the API?
Here is my router in Node/Express:
// route to get city
app.get('/cities/:zip', function(req, res) {
// use mongoose to get the city in the database
console.log(req.params.zip);
var query = City.find({"zip" : req.params.zip});
query.exec(function(err, city) {
if (err)
res.send(err);
res.json(city);
});
});
// route to find cities within 50 miles
app.get('/matches/:latMin/:latMax/:lonMin/:lonMax', function(req, res) {
console.log(req.params.latMin + req.params.latMax + req.params.lonMin + req.params.lonMax);
var matches = City.find({latitude: {$gt: req.param.latMin, $lt:req.params.latMax }, longitude : {$gt :req.param.lonMin, $lt : req.param.lonMax}});
matches.exec(function(err, match){
if(err)
res.send(err);
console.log(match);
res.json(match);
});
});
app.get('*', function(req, res) {
res.sendfile('./public/views/index.html'); // load our public/index.html file
});
Here is my Angular Controller
$scope.update = function (zip) {
City.get({zip : zip}).success(function(response){
$scope.weather = response
}).then(function(response){
$scope.weather = response.data;
})
if(zip.length = 5){
$http.jsonp('http://api.openweathermap.org/data/2.5/weather?zip='+ zip +',us&callback=JSON_CALLBACK&units=imperial').success(function(data){
$scope.data=data;
});
var box = getBoundingBox([$scope.weather[0].latitude, $scope.weather[0].longitude], 50);
City.matches(box[1], box[3], box[0], box[2]).success(function(response){
$scope.matches = response
}).then(function(response){
$scope.matches = response.data;
console.log($scope.matches);
})
}
res.send does not return; the call continues to res.json. And please use braces. Please. Maybe they don't look cool or whatever. Just use them.
if (err) { handleError(res, err); return; }
res.status(200).json(city);
Further down, keeping things DRY:
function handleError(res, err) {
res.status(500).json(err);
}

Resources