Node.js routes with parameters - node.js

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

Related

Express router ordering for params in beginning of url path

I am using express and I want to have my user profile URLs like this: example.com/:username
However, I still need other URLs such as example.com/login and example.com/view/:id
If I order the router like this, it treats "login" as a username when a request is sent to example.com/login:
router.get('/:username', function (req, res, next) {
res.render('profile', {data: req.params.username});
})
router.get('/login', function (req, res, next) {
res.render('login', {data: null});
})
router.get('/view/:id', function (req, res, next) {
res.render('view', {data: req.params.id});
})
If I put the /:username router at the end, everything works correctly. However, if someone went to example.com/view (without an id), I need it to send an error that the view controller didn't receive an id. Instead, it sees it as a username again and instead sends an error that the username doesn't exist.
What is the cleanest way to solve this? Do I just have to add a router for all base url paths? (Something like this):
router.get('/login', function (req, res, next) {
res.render('login', {data: null});
})
router.get('/view/:id', function (req, res, next) {
res.render('view', {data: req.params.id});
})
router.get('/view', function (req, res, next) {
res.render('viewError', {data: null});
})
router.get('/:username', function (req, res, next) {
res.render('profile', {data: req.params.username});
})
I am not entirely sure if this is the right way to do it, but then again this sounds like something I might encounter and I would like it to be solved by this method until I find a better solution.
The below solution uses a single route for the path format /:value, be it login, view or any username, hence you could put in a simple if-else-if or switch to give control to respective controllers or just simply render a view from it. This way the order in which it has to be handled doesn't matter at all.
router.get("/:username", function(req, res, next) {
if (req.params.username === "login") {
res.render("login", { data: null });
} else if (req.params.username === "view") {
res.render("viewError", { data: null });
} else {
res.render("profile", { data: req.params.username });
}
});
router.get("/view/:id", function(req, res, next) {
res.render("view", { data: req.params.id });
});

mongoose: how to search mongoDB with mongoose

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: []
});
});
});

how to send parameters to an ejs page from node js

I am passing the title to the EJS pages from node js as below
router.get('/Home', function(req, res, next) {
res.render('Pages/Home', { title: 'Home' });
});
Can I pass a second parameter along with this as..?
router.get('/Home', function(req, res, next) {
res.render('Pages/Home', { title: 'Home' },{ role: 'Admin' });
});
Yes you can but you need to wrap all your needed parameters in one object like so:
router.get('/Home', function(req, res, next) {
res.render('Pages/Home', { title: 'Home', role: 'Admin' });
});

how to group api in express

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

node express.Router().route() vs express.route()

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

Resources