Express + Angular update route: Error: Cannot PUT - angularjs

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'...

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.

Angular API call fails in MEAN application

In a MEAN app I am trying to allow an authorised user (email and password login) to change their username.
I can successfully use Postman to PUT a new username to http://localhost:3000/api/users/xxxxxxxxxxxxxxxx.
But the angular code fails.
Here is the relevant part of the edit page:
<form ng-submit="user.saveUser()">
<div class="form-group">
<label> New Username</label>
<input type="text" class="form-control" ng-model="user.userData.name">
</div>
Here is the controller:
.controller('userEditController', function($routeParams, User) {
var vm = this;
vm.type = 'edit';
User.get($routeParams.user_id)
.success(function(data) {
vm.userData = data;
});
// function to save the user
vm.saveUser = function() {
vm.processing = true;
vm.message = '';
// call the userService function to update
User.update($routeParams.user_id, vm.userData)
.success(function(data) {
vm.processing = false;
// clear the form
vm.userData = {};
// bind the message from our API to vm.message
vm.message = data.message;
});
};
});
Here is the service:
// update a user
userFactory.update = function(id, userData) {
return $http.put('/api/users/' + id, userData);
};
at this point userData contains name: “Fred” or whatever was input to the form
and here is the api.js
apiRouter.route('/users/:user_id')
// get the user with that id
.get(function(req, res) {
User.findByIdAndUpdate(req.params.user_id, function(err, user) {
if (err) return res.send(err);
// return that user
res.json(user);
});
})
// update the user with this id
.put(function(req, res) {
console.error(req.params.user_id);
User.findById(req.params.user_id, function(err, user) {
if (err) return res.send(err);
// set the new user information if it exists in the request
if (req.body.name) user.name = req.body.name;
// save the user
user.save(function(err) {
if (err) return res.send(err);
// return a message
res.json({ message: 'User updated!' });
});
});
});
(I had to use findByIdAndUpdate instead of findById because of a CastError.)
Although the console states:
XHR finished loading: PUT http:/localhost/3000/api/users/user_id
The value of req.params.user_id is just user_id.
The terminal shows:
PUT /api/users/user_id 200 4.040 ms - 2273
GET /api/users/user_id - - ms - -
GET /api/users/user_id - - ms - -
GET /api/users/user_id - - ms - -
Like I say Postman can communicate with the API and can update without problems. I am stumped, and hopefully someone will put me out of my misery
I had to change tack with this one. The fact that a manually entered user_id in Postman worked should have told me that the user_id provided by the Angular code was not correct. So I made sure that the JWT included the user_id:
var token = jwt.sign({
name: user.name,
email: user.email,
user_id: user._id
Then added an api endpoint to get user information:
apiRouter.get('/me', function(req, res) {
res.send(req.decoded);
});
Then connected a service:
userFactory.get = function() {
return $http.get('/api/me/');
};
Then in the controller I could call get:
User.get()
.success(function(result) {
$scope.user_id = result.user_id;
});
$scope.user_id now has the correct user_id which I can pass into the update method:
User.update($scope.user_id, vm.userData)
.success(function(data)
So now it works as intended.

POST and GET images to/out of MongoDB in Angular

I´m making an angular application, which gives users the possibilities, to manage their projects. I´ve got nodeJS & express serveside and MongoDB as my database.
I want to achieve, that a user can upload media(images under 16MB, so no need to use GridFS) to their projects and that you can display which project, has which media attached.
I´m not getting the images, nor an error. How can I pass the project_Id from angular, to my route, to find the media attached to the project? Is this way of trying to POST and GET the media the right way?
The model for projects and for media:
var mediaSchema = mongoose.Schema({
media : {data: Buffer, contentType: String},
project_id : String,
updated_at : {type: Date, default: Date.now }
});
var projectSchema = mongoose.Schema({
author : String,
name : String,
description : String,
tags : String,
updated_at : {type: Date, default: Date.now },
active : {type: Boolean, default: false}
});
The routing
var Media = require('./models/media.js');
//GET all the media
app.get('/uploads/', function(req, res, next){
Media.find(function (err, media){
if (err) return next (err);
res.json(media);
});
});
//GET one item
app.get('/uploads/media/:projectId', function(req, res, next){
Media.findOne(req.params , function (err, media){
if (err) return next (err);
res.json(media);
});
});
Managing the uploads
app.use(multer({ dest: './uploads/',
rename: function (fieldname, filename) {
return filename+Date.now();
},
onFileUploadStart: function (file) {
console.log(file.originalname + ' is starting ...')
},
onFileUploadComplete: function (file) {
console.log(file.fieldname + ' uploaded to ' + file.path)
done=true;
}
}));
var Media = require('./app/models/media.js');
//POST media to the upload directory
app.post('/uploads/', function(req, res){
if(done==true){
Media.create(req.body, function(err, post){
console.log(req.files);
res.end('File uploaded');
});
}
});
Angular Controller
var app = angular.module('myApp', []);
app.controller('projectCtrl', function($scope, $http) {
$scope.myVar = false;
$scope.toggle = function() {
$scope.myVar = !$scope.myVar
};
$http.get('/profile/project/').then(function (res){
$scope.projects = res.data;
});
//GET Media
var projectId = {{projects._id}};
$http.get('/uploads/media' + projectId).succes(function(data){
console.log('Medien-Daten erhalten');
$scope.media = data;
});
});
Kind regards from Germany,
David
Update (new Errors)
Trying to implement a solution, I get problems with my scopes. When I´m adding the $http.get for the media, my other scope seem to fetch no data... they are shown like this:
Update 2(scope error fixed)
Fixed the error in the controller. I hadn´t defined a var for projectId, that caused the error.
Managed to make the GET request work, and my application is looking for entries in the database. But i can´t manage to see any..
Your use of .find is incorrect in the get all function.
See http://mongoosejs.com/docs/api.html#query_Query-find
Media.find({}, function (err, media){
if (err) return next (err);
res.json(media);
});
This will return all documents.

Updating database with node.js and angular

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);
});
});

AngularJS reload data after PUT request

Should be a fairly easy one here for anyone who knows Angular. I am trying to update the data that is displayed after I make a PUT request to update the object. Here is some code:
Post service (services/post.js)
'use strict';
angular.module('hackaboxApp')
.factory('Post', function($resource) {
return $resource('/api/posts/:id', {id : '#id'}, {
'update': { method: 'PUT' }
})
});
Server side controller function that gets executed when trying to update data (lib/controllers/api.js)
exports.editsave = function(req, res, next) {
var posty = req.body;
console.log(posty._id.toString() + " this is posty");
function callback (err, numAffected) {
console.log(err + " " + numAffected);
if(!err) {
res.send(200);
//res.redirect('/forum');
}
}
Post.update(posty, { id: posty._id.toString() }, callback);
};
This is the console output for the above code:
53c54a0d4960ddc11495d7d7 this is posty
null 0
So as you can see, it isn't affecting any of the MongoDB documents, but it also isn't producing errors.
This is what happens on the client (Angular) side when a post is updated:
$scope.saveedit = function() {
console.log($scope.post._id + " post id");
// Now call update passing in the ID first then the object you are updating
Post.update({ id:$scope.post._id }, $scope.post, function() {$location.path('/forum')});
};
After the redirect, $location.path('/forum'), none of the data is displayed as being updated...when I look in the database...nothing has changed either...it is like I am missing the step to save the changes...but I thought that update (a PUT request) would do that for me.
I use ng-init="loadposts()" when the /forum route is loaded:
$scope.loadposts = function() {
$http.get('/api/posts').success(function (data) {$scope.posts = data});
};
Shouldn't all the new data be loaded after this? Any help would be appreciated. Thanks!
Your server side output indicate that the update query doesn't match any document in the database.
I'm guessing that you are using Mongoose in NodeJS server side code to connect to mongodb.
If that the case, your update statement seems incorrect.
Instead of { id: .. } it should be { _id: .. }
Also the conditions object and updated object are swapped.
The statement should be like this:
Post.update({ _id: posty._id.toString() }, posty, callback);
If you are not using Mongoose, please eloborate more on which library you are using or better than that, show the code where the Post variable is defined in your server side code.
Ok I got it.
the problem is that you are not using the Angular resource api correct.
This code need to be changed:
$scope.saveedit = function() {
console.log($scope.post._id + " post id");
Post.update({ id:$scope.post._id }, $scope.post, function() {$location.path('/forum')});
};
Into:
// Update existing Post
$scope.saveedit = function() {
var editedpost = new Post($scope.post); //New post object
editedpost.$update(function() {
$location.path('/forum');
}, function(errorResponse) {
$scope.error = errorResponse.data.message;
});
};
And as for the server code (taken from my own working module):
exports.update = function (req, res) {
var post == req.post;
post = _.extend(post, req.body);
post.save(function (err) {
if (err) {
return res.send(400, {
message: getErrorMessage(err)
});
} else {
res.jsonp(post);
}
});
};

Resources