MEAN Stack CRUD update 404 error - node.js

Heads up, noob coming through. Trying to build a MEAN stack todo list. So far I've gotten everything to work except for the update option. What I've done is set up the application so that it prompts the user to write in the item they want to update. So say they add the item 'ddd.' The update button would then appear beside the item, and then the user would be given a prompt, asking them to enter the new item. The problem is whenever the user does in fact enter the new item to replace the old, nothing happens, and I instead get a 404 error in the command prompt. Any help would be much appreciated. Below you'll find my controller, routes, index.html
routes/api
var Todo = require('./models/todo');
module.exports = function(app) {
// api ---------------------------------------------------------------------
// get all todos
app.get('/api/todos', function(req, res) {
// use mongoose to get all todos in the database
Todo.find(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
app.post('/api/todos', function(req, res) {
// create a todo, information comes from AJAX request from Angular
Todo.create({
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(function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
// delete a todo
app.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(function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
//update to do
app.put('/api/todos/_id', function(req, res) {
Todo.findById(req.params._id, function(err, todos){
todo.text = req.body.text;
console.log(todos);
todos.save(function() {
if (!err) {
res.send(todos);
} else if (err) {
res.send(err);
}
});
});
});
// application -------------------------------------------------------------
app.get('*', function(req, res) {
res.sendfile('./public/index.html'); // load the single view file (angular will handle the page changes on the front-end)
});
};
controller
var baselTodo = angular.module('baselTodo', []);
function mainController($scope, $http) {
$scope.formData = {};
// when landing on the page, get all todos and show them
$http.get('/api/todos')
.success(function(data) {
$scope.todos = data;
})
.error(function(data) {
console.log('Error: ' + data);
});
// when submitting the add form, send the text to the node API
$scope.createTodo = function() {
$http.post('/api/todos', $scope.formData)
.success(function(data) {
$('input').val('');
$scope.todos = data;
})
.error(function(data) {
console.log('Error: ' + data);
});
};
// delete a todo after checking it
$scope.deleteTodo = function(id) {
$http.delete('/api/todos/' + id)
.success(function(data) {
$scope.todos = data;
})
.error(function(data) {
console.log('Error: ' + data);
});
};
$scope.updateTodo = function(id) {
$scope.newItem = prompt("Please enter your new item:", "");
$http.put('/api/todos/' + id, {formData: $scope.newItem}).success(function(data) {
$scope.todos = data;
});
$http.get('/api/todos').success(function(data) {
$scope.todos = data;
});
};
};

It looks like, in your routes api:
app.put('/api/todos/_id', function(req, res) {
You forgot the colon in the path, therefore you can't access that variable. Try:
app.put('/api/todos/:_id', function(req, res) {

Related

Type.Error app.address is not a function

I'm trying test my node app ,I am able to get post,get and put to work but I can't get delete to work I keep on getting the following error "Type.Error app.address is not a function"
This is my test class :
var supertest = require("supertest");
var should = require("should");
// This agent refers to PORT where program is runninng.
var server = supertest.agent("http://localhost:8000");
// UNIT test begin
describe("Contacts GET unit test",function(){
// #1 should return contacts representation in json
it("should return collection of JSON documents",function(done){
// calling home page api
server
.get("/api/contacts/")
.expect("Content-type",/json/)
.expect(200) // THis is HTTP response
.end(function(err,res){
// HTTP status should be 200
res.status.should.equal(200);
done();
});
});
it("should add a new contact",function(done){
// post to /api/contacts
server.post('/api/contacts')
.send({name:"Contact 99"})
.expect("Content-type",/json/)
.expect(201)
.end(function(err,res){
res.status.should.equal(201);
done();
});
});
it("should update contact",function(done){
// post to /api/contacts
// calling home page api
server.put("/api/contacts/58e275d0aef2392e10eaba6e")
.expect("Content-type",/json/)
.expect(200) // THis is HTTP response
.end(function(err,res){
res.body._id.should.equal("58e275d0aef2392e10eaba6e");
done();
}
);
}
);
it("should delete contact",function(done){
// post to /api/contacts
// calling home page api
const superserver = supertest(server);
server.get("/api/contacts")
.expect("Content-type",/json/)
.expect(200) // THis is HTTP response
.end(function(err,res){
const id = res.body[0]._id;
server.delete("/api/contacts/"+id)
.expect("Content-type",/json/)
.expect(200) // THis is HTTP response
.end(function(err,res){
res.body._id.should.equal(id);
res.body.should.have.property("name");
done();
}
);
}
);
});
});
and this my main class with all the functionalities :
'use strict';
var _ = require('lodash');
var Contact = require('./contact.model');
// Get list of contacts
exports.index = function(req, res) {
// Connect to the db
Contact.find(function (err, contacts) {
if(err) { return handleError(res, err); }
return res.json(200, contacts);
});
} ;
// Creates a new contact in datastore.
exports.create = function(req, res) {
Contact.create(req.body, function(err, contact) {
if(err) { return handleError(res, err); }
return res.json(201, contact);
});
};
// Updates an existing contact in the DB.
exports.update = function(req, res) {
if(req.body._id) { delete req.body._id; }
Contact.findById(req.params.id, function (err, contact) {
if (err) { return handleError(res, err); }
if(!contact) { return res.send(404); }
var updated = _.merge(contact, req.body);
updated.save(function (err) {
if (err) { return handleError(res, err); }
return res.json(200, contact);
});
});
};
// delete an existing contact in datastore.
exports.delete = function(req, res) {
Contact.findById(req.params.id, function (err, contact) {
if(err) { return handleError(res, err); }
if(!contact) { return res.send(404); }
contact.remove(function(err) {
if(err) { return handleError(res, err); }
return res.send(201);
});
});
};
function handleError(res, err) {
return res.send(500, err);
};
This what I get in the command line:
I am not sure if it could help but in your test Class the problem seems to be here (l.62):
const id = res.body[0]._id;
it returns undefined so you get a Type.Error
You should try to debug this line and check the return of :
res.body[0]
PS : api\contacts\test\testContancts.js sure about the name file ?

Node: check `boolean` value from defined `model`

I am trying to update position in my todo list
var Todo = mongoose.model('Todo', {
text : String,
done : Boolean
});
database mode has two elements, and I want to update only boolean - done.
app.put('/api/todos/:todo_id', function(req, res) {
var query = { _id: req.params.todo_id };
Todo.update(query,
{ done: true
}, function(err, todo) {
if (err)
res.send(err);
Todo.find(function(err, todos) {
if (err)
res.send(err)
res.json(todos);
});
});
});
I would like to check actual value and then update. Done is from mongoose model so I can't check it like that?
if (done != true){
done: true }
else {
done: false }
Is something like that possible?
app.put('/api/todos/:todo_id', function(req, res) {
Todo.findById(req.params.todo_id, function(err, todo) { // get todo by Model.findById
if (err) return res.send(err);
todo.done = !todo.done; // toggle todo's done field
todo.save(function(err) { // save to database
if (err) return res.send(err);
res.json(todo); // return the saved todo
});
});

RESTful API singular route with a single object to retrive and update (options parameters)

Hi i'm stucked trying to create a route in the RESTful API server in express.
I've configured other routes and now i need to configure an ('/options) or ('/profile') singular route where there is only one object to retrive and update.
Basically i need to do the same of the json-server module in the Singular routes section.
So when i visit the /options endpoint i got the predefined object with this schema
{
tax: Number,
inps: Number,
ritenuta: Number,
banca: {
nome: String,
iban: String
}
}
to update.
Here's my actual routes for /options:
var Option = require('../models/option');
var express = require('express');
var router = express.Router();
router.route('/options')
.get(function(req, res) {
Option.find(function(err, options) {
if (err) {
return res.send(err);
}
res.json(options);
});
})
.post(function(req, res) {
var option = new Option(req.body);
option.save(function(err) {
if (err) {
return res.send(err);
}
res.send({message: 'Option Added'});
});
});
// Save an option
router.route('/options/:id').put(function(req, res) {
Option.findOne({ _id: req.params.id}, function(err, option) {
if (err) {
return res.send(err);
}
for (prop in req.body) {
option[prop] = req.body[prop];
}
option.save(function(err) {
if (error) {
return res.send(err);
}
res.json({message: 'Option updated!'})
});
});
});
// Retrive an option
router.route('/options/:id').get(function(req, res) {
Option.findOne({ _id: req.params.id }, function(err, option) {
if (err) {
return res.send(error);
}
res.json(option);
});
});
// Delete an option
router.route('/options/:id').delete(function(req, res) {
Option.remove({ _id: req.params.id}, function(err, option) {
if (err) {
return res.send(err);
}
res.json({message: 'Option deleted!'});
});
});
module.exports = router;
but it's much complicated. It should be simpler. In fact, in this case i need to get all the options, get the id of options[0] and make a call with the id as params to retrive the object and update.
Any suggestions please?

Why my nodejs requests are slow?

Im new in nodejs, and Im trying to learn by creating an app that has a list of users, that I can add and remove those users. Im using angularjs in frontend to send request to nodejs and after that to mongodb. The problem is that, if I click a lot of times in the button "adduser" a lot of times, my app goes slow.
To interact to mongodb I use:
app.get('/users',function (req, res) {
mongoose.model('Usuario').find(function (err, list) {
res.send(list);
});
});
app.post('/addusuario', function (req,res) {
var usuario = new Usuario(req.body);
usuario.save(function (err) {
if (err) {
console.log(err);
} else {
console.log('Usuario salvo com sucesso');
}
}); });
app.delete('/delusuario/:id', function (req, res) {
var id = req.params.id;
mongoose.model('Usuario').findByIdAndRemove(id , function(err) {
if(err) {
console.log(err);
} else {
console.log('Usuario removido com sucesso!');
}
});
});
Im my angularapp:
app.controller('AppCtrl', function($scope, $http, Data) {
function reload() {
Data.get('users').then(function(data){
$scope.usuarios = data;
console.log(data);
});
};
$scope.addUsuario = function(usuario) {
Data.post('/addusuario', usuario);
reload();
};
$scope.deletarUsuario = function(id) {
Data.delete("/delusuario/"+id).then(function(result) {
});
reload();
};
reload();
});
I dont know why it is becaming slow after I click to add user more than 3 times..
What I see in your code that you are not sending an response back to the user, you should do something after insert or delete in the database. res.end();
You should rewrite your code in the following way:
app.get('/users',function (req, res) {
mongoose.model('Usuario').find(function (err, list) {
res.send(list);
});
});
app.post('/addusuario', function (req,res) {
var usuario = new Usuario(req.body);
usuario.save(function (err) {
if (err) {
console.log(err);
res.json({err: err});
} else {
res.json({ok: true});
console.log('Usuario salvo com sucesso');
}
}); });
app.delete('/delusuario/:id', function (req, res) {
var id = req.params.id;
mongoose.model('Usuario').findByIdAndRemove(id , function(err) {
if(err) {
console.log(err);
res.json({err: err});
} else {
res.json({ok: true});
console.log('Usuario removido com sucesso!');
}
});
});
You block the stack by not returning the response to the client. And this is most probably the cause of your slow request.

PUT and DELETE always route to GET in Node + Express

I'm a beginner in Node/Express. I tried to make an CRUD application but stuck at update and delete. I think my router code is problematic but I don't know why. The following code is in my controller, everything works but PUT and DELETE. It always route to GET. I tried to use next(); but it returns this error: Can't set headers after they are sent..
I can make the delete works by using GET /:company_id/delete but it's not a good and standardized solution. How can I get update and delete process worked?
'use strict';
var Companies = require('../../models/companies');
module.exports = function (router) {
// INDEX
// accessed at GET http://localhost:8000/companies
router.get('/', function (req, res) {
Companies.find(function(err, model) {
if (err) {
res.send(err);
}
else {
res.format({
json: function () {
res.json(model);
},
html: function () {
res.render('companies/index', model);
}
});
}
});
});
// CREATE VIEW
// accessed at GET http://localhost:8000/companies/create
router.get('/create', function (req, res) {
res.render('companies/create');
});
// CREATE DATA
// accessed at POST http://localhost:8000/companies
router.post('/', function (req, res) {
var name = req.body.name && req.body.name.trim();
var type = req.body.type && req.body.type.trim();
// VALIDATION
if (name === '') {
res.redirect('/companies/create');
return;
}
var model = new Companies({name: name, type: type});
model.save(function(err) {
if (err) {
res.send(err);
}
else {
res.redirect('/companies');
}
});
});
// READ
// accessed at GET http://localhost:8000/companies/:company_id
router.get('/:company_id', function(req, res) {
Companies.findById(req.params.company_id, function(err, model) {
if (err) {
res.send(err);
}
else {
res.render('companies/read', model);
}
});
});
// UPDATE VIEW
// accessed at GET http://localhost:8000/companies/:company_id/edit
router.get('/:company_id/edit', function(req, res) {
Companies.findById(req.params.company_id, function(err, model) {
if (err) {
res.send(err);
}
else {
res.render('companies/edit', model);
}
});
});
// UPDATE DATA
// accessed at PUT http://localhost:8000/companies/:company_id
router.put('/:company_id', function(req, res) {
Companies.findById(req.params.company_id, function(err, model) {
if (err) {
res.send(err);
}
else {
model.name = req.body.name;
model.type = req.body.type;
model.save(function(err) {
if (err) {
res.send(err);
}
else {
res.redirect('/companies');
}
});
}
});
});
// DELETE
// accessed at DELETE http://localhost:8000/companies/:company_id
router.delete('/:company_id', function (req, res) {
Companies.remove({ _id: req.params.company_id }, function(err) {
if (err) {
res.send(err);
}
else {
res.redirect('/companies');
}
});
});
};
HTML forms only support GET and POST. XMLHTTPRequest supports PUT and DELETE however, so you may have to go that route OR use something like method-override to allow HTML forms to submit using other HTTP verbs.

Resources