Node JS Express routing with method-override. Can someone explain why _method=DELETE works with my router using route.post, but not route.delete? - node.js

app.js
const methodOverride = require ('method-override');
const app = express();
// Method Override Midware
app.use(methodOverride('_method'));
Router
const express = require('express');
const router = express.Router();
// Pass all routes through adminController
const adminController = require('../controllers/adminController');
router.route('/posts/delete/:id')
.post(adminController.deletePost);
//.delete(adminController.deletePost);
HTML
<form action="/admin/posts/delete/{{id}}?_method=DELETE" method="post">
<button class="btn btn-sm btn-danger" type="submit">Delete Post</button>
</form>
I spent a good while trying to figure this out and it turns out the solution for a successful deletion was to remove route.delete and replace it with route.post in my router. But I don't understand why this works and .delete doesn't. As far as I know, HTML forms can only GET and POST, but I assumed method-override would circumnavigate this and let me type .delete directly. So now I'm confused as to whether it's the import for override that's not working properly, or if it's working fine and I still need to .post every time regardless and just change the endpoint's method in my HTML?
Thank you

Related

What is the difference between the two calls to express()

I have 2 require('express) calls.
First:
const express = require('express');
const app = express();
Second:
const Router = require('express');
const router = new Router();
What is the difference, why in the first we call a function, and in the second we create an object, if the methods are the same in both (use, get, post, etc)?
I think your question missed something. Your second example shows this:
const Router = require('express');
... but I think you meant to do this:
const Router = require('express').Router;
... regardless, the following should help you better understand.
In express, you can think of Routers as little mini applications... lightweight express apps... which have their own routing. In fact, the main "express" object is itself a Router. For example, you might have a bunch of endpoints for managing users:
// ./routes/user-routes.js
const userRoutes = new express.Router();
userRoutes.get('/', getAllUsers);
userRoutes.get('/:userId', getUserById);
userRoutes.post('/', createUser);
userRoutes.put('/:id', updateUser);
userRoutes.delete('/:id', removeUser);
Notice how none of the urls have anything like /users/ inside them. This is important because this little mini app can now be "mounted" (for lack of better terms) in a larger express app like follows:
const express = require('espress');
const userRoutes = require('./routes/user-routes');
const app = express();
app.use('/path/to/users', userRoutes);
Notice how the userRoutes were "mounted" on the /path/to/users such that all user requests will happen to the following URLs:
GET /path/to/users - get all users
GET /path/to/users/1234 - get user with id "1234"
... you get the point
This is mostly a convenient way to think about your app as a bunch of smaller mini apps which are orchestrated together.
Your second call is incorrect, you are just calling (requiring) express which is similar to your first call.
I never did const router = new Router();, so I'm not sure what that accomplish.
I generally do-
const router = require('express').Router();
router.get();
Even though with your first call you can do
app.get() and app.post()
According to express explanation
express.Router class is used to create modular, mountable route handlers. A Router instance is a complete middleware and routing system
Read more about it here
GeekforGeeks explains express.Router() very well

Generic route prefix + specific route in Node Express

I have a system where, before specifying the data you want to access, you need to provide the company you are accessing from, to check for authorization.
For example, to get products, materials and users:
GET company/123123/product
GET company/123123/material
GET company/123123/user
When creating the express routes in node JS, I'm using the prefix "company/:id" in all my routes declarations:
app.get("/company/:id/product", callbackProduct);
app.get("/company/:id/material", callbackMaterial);
app.get("/company/:id/user", callbackUser);
The question is, is there any way to generalize this 'company' part of the route, in a way that I don't need to re-write it in all routes?
For example:
app.something("/company/id:/*", genericCallback);
app.get("/product", callbackProduct);
app.get("/material", callbackMaterial);
app.get("/user", callbackUser);
What you could do is to use express.Router.
In an company.routes.js you would write something like that.
const express = require("express");
const CompanyRouter = express.Router();
CompanyRouter.get("/:id/product", callbackProduct);
CompanyRouter.get("/:id/material", callbackMaterial);
CompanyRouter.get("/:id/user", callbackUser);
module.exports = CompanyRouter;
And in your server.js file you would do the following.
const express = require("express");
const CompanyRouter = require("./path/to/CompanyRouter.js")
const app = express();
app.use("/company", CompanyRouter);
app.listen(3000);

typescript express get does not work in separate files

I'm currently converting my node code to node-ts to help our development flow for someone that is going to help out.
I tried using this information (typescript node.js express routes separated files best practices) initially but that didn't work, so as of right now I have this below
In my index.ts I have this on the bottom
import Auth from "./routes/Auth";
app.use('/auth', Auth.Routing());
export = app;
Then in my ./routes/Auth.ts I have this
const Routing = function() {
app.get('/session', User.session);
return app;
}
export = { Routing };
When I try to access /auth/session all it returns is index_1.default.get.
Using the link above, I attempted to use const router = express.Router(); and then export = router and what not but was unable to get it to work for that either with the same error.

Cannot POST /addfriend error using Express

I am trying to create a simple form handler using express. Here is a similar question but I can't related it with my problem. I have written all of my file Here anyone can check it by using all of my file. For better understanding I copy my code here:
app.js code:
const express = require('express');
const app = express();
//routes
app.get('/',function(req,res){
res.send('This is root dir');
});
app.get('/friends',function(req,res){
var friends=['sakib','emon','rayhan'];
res.render('friends.ejs',{friends:friends});
});
app.get('/addfriend',function(req,res){
res.send('ADD friend page launch!!!!!');
});
app.listen(3000,function(){
console.log("server has started on port 3000!!!");
});
ejs(friends.ejs) code:
<h1>Here is list of your Friend:</h1>
<%friends.forEach(function(friend){%>
<li><%=friend%></li>
<%});%>
<form action="/addfriend" method="POST">
<input type="text" name="friend" placeholder="name">
<button>
Submit
</button>
</form>
When I type any name in the input box and clicked Submit it didn't post to /addfriend. I didn't understand where is my problem. Please goto input box(link) after started the server.
For better understand what's my actual problem is then please use goorm IDE(shared file) where I uploaded everything.
You are using get request instead of post for addfriend.
app.post('/addfriend',function(req,res){
console.log("I'm called wohoo!");
res.send('ADD friend page launch!!!!!');
});

how to send the selected drop down element from client to server using node js - express

I am new to node js and i am stuck to send the selected drop down element (like java,angular see below ex ) from client to server using node js - express. When i try to print it in console. system displays an error message "undefined " for drop down elements. Please help me on this. Thanks in advance.
EJS code
<form method="POST" action="/viewreg.html">
<select name="Courses" form="Courses">
<option value="Java">Java</option>
<option value="Angular">Angular</option>
<option value="Automation">Automation</option>
</select>
<input type='submit'name ='register' onclick="form.action='viewreg.html'"
</form>`
Server side -
const http = require('http');
const express = require('express');
const bodyparser=require('body-parser');
const path=require('path');
const hostname = 'x.x.x.x'
const port = 80;
const app = express();
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({extended:true}));
app.use(express.static(path.join(__dirname,'public')));
app.set('view engine','ejs');
app.set('views',path.join(__dirname,'views'));
app.use(bodyparser.json());
app.use(bodyparser.urlencoded({extended:true}));
const dir=path.join(__dirname,'public');
app.set('view engine','ejs');
app.set('views',path.join(__dirname,'views'));
app.post('/viewreg.html',function(req,res) {
const newuser= {
emp_name:req.body.emp_name,
emp_id:req.body.emp_id,
phone_no:req.body.phone_no,
Team:req.body.selectpicker,
courses:req.body.Courses,
}
console.log(newuser);
});
You need to revisit the below issues which exist in your code.
Change your action url from action="/viewreg.html"> to
action="/viewreg">
There is no need to have onclick="form.action='viewreg.html'" in
your submit button.
You don't have an ID attribute attached to your <select> tag
where as you have a form attribute incorrectly over there.
You need to re-write your ejs tempalte as,
<form method="POST" action="/viewreg">
<select name="Courses" id="Courses">
<option value="Java">Java</option>
<option value="Angular">Angular</option>
<option value="Automation">Automation</option>
</select>
<input type='submit'name ='register'>
</form>
Also try changing your console.log(newuser); as,
console.log(req.body.Courses);
which will resolve your issue.
Hope this helps!

Resources