I am using Node/Express and mongoose to build an app. I am creating 'Photo' objects in my database (schema shown below) which is basically just an image object.
var PhotoSchema = new mongoose.Schema({
image: { data: Buffer, contentType: String },
name: String
});
I can successfully upload and create photo objects and now I am creating an /images view where I want to extract every photo object and render it as an image. I am using ejs for my views. After doing some googling I hav come up with the following for my images.ejs file :
<% photos.forEach(function(photo){ %>
<img src="/img/<%=photo._id%>" >
<% }) %>
When I load /images it says "photos is not defined".
This is the first time I have tried to directly extract mongoose objects onto an ejs page - is there something else I need to do/include so that my function understands I am referring to the photo objects in my database?
I also have the following routes:
router.get('/img', function (req, res, next) {
try {
Photo.findOne({}, function (err, doc) {
if (err)
res.send(err);
if (doc) {
res.contentType(doc.image.contentType);
res.send(doc.image.data);
}
});
}
catch (e) {
res.send(e);
}
});
router.get('/img/:id', function (req, res) {
try {
Photo.findOne({ _id: req.params.id }, function (err, doc) {
if (err)
res.send(err);
res.setHeader('Cache-Control', 'public, max-age=3000000');
res.contentType(doc.image.contentType);
res.send(doc.image.data);
});
}
catch (e) {
res.send(e);
}
});
router.get('/images', function (req, res) {
try {
Photo.find({}, function (err, doc) {
if (err)
res.send(err);
res.render('images', { images: doc });
});
}
catch (e) {
res.send(e);
}
});
Thank you!
Your view variable is images (res.render('images', { images: doc });), not photos. Rename one or the other and it should work.
Related
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?
I am new to the whole mean stack. I am about to create a CRUD application. I already have the easy ones, C and R but now I want to go for D. Unfortunately, when I try to delete an entry I get a 500 error. My routes are getting called but after that nothing happens.
Html
<div ng-repeat="article in articles">
<form ng-click="deleteArticle(article)">
<button type="submit" class="btn btn-primary">Delete</button>
</form>
</div>
Angular
The part that is in my controller..
$scope.deleteArticle = function(article) {
articlesFactory.removeArticle(article) }
And the part that is getting called in a factory:
art.removeArticle = function(article) {
return $http.put('/articles/' + article._id + '/remove')
};
Routes
...
router.param('article', function(req, res, next, id) {
var query = Article.findById(id);
query.exec(function (err, article) {
if (err) { return next(err); }
if (!article) { return next(new Error("Unable to find this article.")); }
req.article = article;
return next();
});
});
...
router.put('/articles/:article/remove', function(req, res, next) {
console.log("I arrived in the routes")
req.article.remove(function(err, article) {
if (err) { return next(err); }
res.json(article);
});
});
...
Model
var ArticleSchema = new mongoose.Schema({
title: String,
content: String,
likes: { type: Number, default: 0 },
comments: [{ type: mongoose.Schema.Types.ObjectId, ref: 'Comment' }]
});
ArticleSchema.methods.remove = function(callback) {
this.remove(callback);
Should use the delete method of HTTP. And try this logic, it's from angular-fullstack controller templates (I'd recommend using it over creating your own endpoints, here's the link):
router.delete('/articles/:id/remove', function(req, res, next) {
Article.findById(req.params.id, function (err, article) {
if(err) { return next(err); }
if(!article) { return res.send(404); }
article.remove(function(err) {
if(err) { return handleError(res, err); }
return res.send(204);
});
});
});
You'll need to update this as well to use delete:
art.removeArticle = function(article) {
return $http.delete('/articles/' + article._id + '/remove')
};
I know this is an old post, but I stumbled upon it as i had the same problem, so maybe it can be useful for someone.
After trying your code and using some things of TommyMac's answer, this was my outcome and should help:
Controller:
Your controller part was ok:
$scope.deleteArticle = function(article) {
articlesFactory.removeArticle(article) }
Factory: You should use DELETE instead of PUT
It worked for me with the following function:
router.delete('/articles/:article/remove', function(req, res, next) {
req.article.remove(function(err) {
if (err) {
return next(err);
}
return res.sendStatus(204);
});
});
Model: for me, it worked without providing a "remove" function at the model (apparrently there is a default function), so remove the following snippet from your code:
ArticleSchema.methods.remove = function(callback) {
this.remove(callback);
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.
I am building a JSON API with ExpressJS, NodeJS and Mongoose:
Input -> id:
app.get('/folder/:id', function (req, res){
return Cars.find({reference: req.params.id}, function (err, product) {
if (!err) {
console.log(product);
return res.send(product);
} else {
return console.log(err);
}
});
});
It shows well the JSON:
[{"_id":"B443U433","date":"2014-08-12","reference":"azerty","file":"087601.png","
....:.
{"_id":"HGF6789","date":"2013-09-11","reference":"azerty","file":"5678.pnf","
...
I just want to display the _id in the JSON, so it is good when I have lots of data.
How I can do that? Something like a filter?
You can chain calls to select and lean to retrieve just the fields you want from the docs you're querying:
app.get('/folder/:id', function (req, res){
return Cars.find({reference: req.params.id}).select('_id').lean().exec(
function (err, product) {
if (!err) {
console.log(product);
return res.send(product);
} else {
return console.log(err);
}
});
});
You would have to iterate over your "products" object to obtain the ids
Something like this:
(Disclaimer: I haven't tested this)
app.get('/folder/:id', function (req, res){
return Cars.find({reference: req.params.id}, function (err, product) {
if (!err) {
console.log(product);
var ids = new Array();
for(var i = 0; i < product.length; i++){
ids.push(product[i]._id);
}
return res.send(JSON.stringify(ids));
} else {
return console.log(err);
}
});
});
--Edit
Also, "products" may already be a JSON string. You may want to parse it before looping.
product = JSON.parse(product);
Other answers are true but I think it's better to limit data in mongoose like this :(it's same as mongo shell commands)
app.get('/folder/:id', function (req, res){
Cars.find({reference: req.params.id} ,{ _id : true } ,function (err, product) {
if (!err) {
console.log(product);
} else {
console.log(err);
}
});
});
In my ExpressJS app I have two routes to the same location, one for 'get' and one for 'post'.
On the 'get' page it dumps all the documents from my MongoDB collection, via MongooseJS, followed by a form to add a new record to the collection.
On the 'post' page it takes in the form data and adds it to the collection, and then displays the same page you see via 'get'.
It works, but after the form is submitted the new record doesn't appear unless I reload the page. I put the code that renders the page at the very bottom, below the part that adds the data to the collection so in my mind that should work but it doesn't.
exports.index = function(req, res){
Server.find({},
function(err, docs) {
if (!err){
res.render('servers', { title: 'verify', results: docs});
}
else { console.log(err);}
}
);
}
exports.add = function(req, res){
newServer = new Server({
name: req.body.name,
os: req.body.os,
osVersion: req.body.osVersion
});
newServer.save(function (err) {
if (err) {
console.log(err);
}
});
Server.find({},
function(err, docs) {
if (!err){
res.render('servers', { title: 'verify', results: docs});
}
else { console.log(err);}
}
);
}
Ok, I seem to make this mistake over an over again with callbacks. I fixed the problem.
exports.add = function(req, res){
newServer = new Server({
name: req.body.name,
os: req.body.os,
osVersion: req.body.osVersion
});
newServer.save(function (err) {
if (err) {
console.log(err);
} else {
Server.find({},
function(err, docs) {
if (!err){
res.render('servers', { title: 'verify', results: docs});
}
else { console.log(err);}
}
);
}
});
}
Yes, those DB queries are async, so callbacks will solve this issue. However, you should look into using promises. Mongoose returns promises by default or you could import your library of choice. They will come in handy when dealing with nested callbacks and queries and also Error handling.