I am learning Express.js, MongoDB and Mongoose, and i am creating a small app that lets me store items to a list.
I am trying to Create a GET /list/search route which allows to search for items in the list, but i haven't gotten it to work.
Here is my code
Routes
const express = require('express');
router = express.Router();
const db = require("../models");
router.get('/', function(req, res, next){
db.List.find().then(function(list){
res.render('index', {list});
});
});
router.get('/new', function(req, res, next){
res.render('new');
});
router.get('/:id', function(req, res, next){
db.List.findById(req.params.id).then(function(list){
res.render('show', {list});
});
});
router.get('/:id/edit', function(req, res, next){
db.List.findById(req.params.id).then(function(list){
res.render('edit', {list});
});
});
router.get('/search', function(req, res, next){
db.List.findOne(req.query.search).then(function(list){
console.log(list);
res.render('show', {list});
});
});
router.post('/', function(req, res, next){
db.List.create(req.body).then(function(list){
res.redirect('/');
});
});
router.patch('/:id', function(req, res, next){
db.List.findByIdAndUpdate(req.params.id, req.body).then(function(list){
res.redirect('/');
});
});
router.delete('/:id', function(req, res, next){
db.List.findByIdAndRemove(req.params.id).then(function(list){
res.redirect('/');
});
});
module.exports = router;
Index.pug
extends base.pug
block content
h1 My List
form(action="/list/search" method="GET")
input(type="text" name="search")
input(type="submit", value="search")
a(href="/list/new") Add New Item!
each item in list
p ITEM: #{item.name} QUANTITY: #{item.quantity}
a(href=`/list/${item.id}/edit`) Edit
my main problem is the GET /search, i want to pass in a search query to the search box and return the result to the render file
router.get('/search', function(req, res, next){
db.List.findOne(req.query.search).then(function(list){
console.log(list);
res.render('show', {list});
});
});
Thanks in advance
You need to specify the parameters as attributes in the query. list will be null, if no matching record was found.
router.get('/search', function (req, res, next) {
db.List.findOne({
name: req.query.name,
age: req.query.age
}).then(function (list) {
console.log(list);
if (list === null) {
return res.render('show', {
list: []
});
}
return res.render('show', {
list: list
});
}).catch((err) => {
console.log('err', err);
return res.render('show', {
list: []
});
});
});
Related
My first time using Node.js/express routes, I cannot match when I use parameters
<a href="/produtos/1/produto-test">
app.use('/produtos', produtosRouter);
//below the produtosRouter, function
router.get('/', function(req, res, next) {
res.render('produtos/:id/:slug', { title: 'test test.' });
});
Does this help?
router.get('/:id/:slug', function(req, res, next){
res.render('<name_of_the_template>', { title: 'test test.'});
});
I am trying to read and pass req.params to another middleware. But I am getting an empty object in response.
var app = require('express')();
app.get('/foo/:bar', function(req,res, next) {
console.log('1 --', req.params);
next();
});
app.use(function(req, res, next) {
console.log('2 --', req.params);
res.end();
})
app.listen(3000);
I am hitting this url -
http://localhost:3000/foo/hello
Output I am getting is -
1 -- { bar: 'hello' }
2 -- undefined
How to pass req.params to another middleware?
AFAIK, req.params is only available in handlers that explicitly set a parameter.
So this works:
app.get('/foo/:bar', function(req,res, next) {
console.log('1 --', req.params);
next();
});
app.use('/foo/:bar', function(req, res, next) {
console.log('2 --', req.params);
res.end();
});
If you don't want that, you need to keep a reference to the params in a different property:
app.get('/foo/:bar', function(req,res, next) {
console.log('1 --', req.params);
req.requestParams = req.params;
next();
});
app.use(function(req, res, next) {
console.log('2 --', req.requestParams);
res.end();
});
//route
app.get('/foo/:bar', yourMiddleware, function(req, res) {
res.send('params: ' + req.params);
});
//middleware
function yourMiddleware(req, res, next) {
console.log('params in middleware ' + req.params);
next();
}
so when I log into my website and navigate within the same url (ex: localhost/private/xxxx), the res.locals.user returns an object.
When I go out of the range (ex: localhost/xxxx), res.locals.user is empty.
/ app.js
...
app.use(passport.session());
app.use(require('./controllers'));
...
/ controllers / index.js
router.use('/private', require('./member.js'));
router.use('/admin', require('./admin.js'));
/* Some basic routes. */
router.get('/', function(req, res, next) {
res.render('index', { ... });
});
After loggin in res.locals.user is still empty here
/ controllers / member.js
router.use(function isMember(req, res, next) {
if(req.isAuthenticated()) {
res.locals.user = req.user;
return next();
}
req.flash('error', 'WHY YOU LITTLE!');
res.redirect('/login');
});
router.get('/', function(req, res, next) {
res.redirect('/private/index');
});
router.get('/something', function(req, res, next) {
res.redirect('/private/somehting');
});
router.get('/darkside', function(req, res, next) {
res.redirect('/private/darkside');
});
res.locals.user correctly returns the user, whether I navigate to /private, /private/something or /private/darkside
Is it cause I use a middleware route when using router.use('/private', require('./member.js')); ? How do I fix this?
res.locals is an object passed to the rendering engine of your app. You can set the user details by req.session.user = user in passport authentication strategy.So that you can access the user from any of your route.
At the end I simply had to add
router.use(function (req, res, next) {
if(req.isAuthenticated()) {
res.locals.user = req.user;
}
return next();
});
before all my routes and remove res.locals.user = req.user; from the member.js file
So it would give me this:
/ controllers / index.js
router.use(function (req, res, next) {
if(req.isAuthenticated()) {
res.locals.user = req.user;
}
return next();
});
router.use('/private', require('./member.js'));
router.use('/admin', require('./admin.js'));
/* Some basic routes. */
router.get('/', function(req, res, next) {
res.render('index', { ... });
});
Here is the example:
var app = require('express')();
function validateToken(req, res, next) {
// Do something with request here
next();
};
app.get('/user/login', function(req, res) {
//code
});
app.post('/user/register', function(req, res) {
//code
})
app.put('/user/register', validateToken, function(req, res) {
//code
})
app.delete('/user/delete', validateToken, function(req, res) {
//code
})
If I have 10 api that need validToken, I should add validToken middleware 10 times, like:
app.method('......', validateToken, function(req, res) {
//code
})
app.method('......', validateToken, function(req, res) {
//code
})
....
app.method('......', validateToken, function(req, res) {
//code
})
app.method('......', validateToken, function(req, res) {
//code
})
How can I group api by using the same middleware?
Here's how to re-use the same callback function for multiple routes (like middleware):
var app = require('express')();
function validateToken(req, res, next) {
// Do something with request here
next();
};
app.get('/user/login', function(req, res) {
// code
});
app.post('/user/register', function(req, res) {
// code
});
// Be sure to specify the 'next' object when using more than one callback function.
app.put('/user/register', validateToken, function(req, res, next) {
// code
next();
});
app.delete('/user/delete', validateToken, function(req, res, next) {
// code
next();
});
Also, you can replace app.METHOD (e.g. .post, .get, .put, etc.) with app.all and your callback will be executed for any request type.
Just wrong, so do not put into mass participation of the (Google translated from: 刚才看错了,改成这样就不用放进传参了)
var group = {url:true,url:true,url:true};
app.use(function(req,res,next){
if(group[req.url]){
// Do something with request here
next();
} else {
next();
}
})
What should I use:
express.Router().route()
or
express.route()
?
Is it true express.Router().route() is someway deprecated?
For the current version of Express, you should use express.Router().route(). See the express documentation for confirmation. express.Router().route() is not depreciated.
For example:
var router = express.Router();
router.param('user_id', function(req, res, next, id) {
// sample user, would actually fetch from DB, etc...
req.user = {
id: id,
name: 'TJ'
};
next();
});
router.route('/users/:user_id')
.all(function(req, res, next) {
// runs for all HTTP verbs first
// think of it as route specific middleware!
next();
})
.get(function(req, res, next) {
res.json(req.user);
})
.put(function(req, res, next) {
// just an example of maybe updating the user
req.user.name = req.params.name;
// save user ... etc
res.json(req.user);
})
.post(function(req, res, next) {
next(new Error('not implemented'));
})
.delete(function(req, res, next) {
next(new Error('not implemented'));
})
Router.route() can use for chainable routes.
Meaning: You have one API for all the METHODS, you can write that in .route().
var app = express.Router();
app.route('/test')
.get(function (req, res) {
//code
})
.post(function (req, res) {
//code
})
.put(function (req, res) {
//code
})