I am setting up a simple blog site and am having problems making the user authentication setup section. What I want to be happening is to have both the Register form and the Login form on the same page (for style reasons) but my issue is is that, to my knowledge, you cannot have two POST methods on one page. I have tried multiple work arounds, like using PUT or checking if the fields are empty, but these all feel hacky and don't really work. Is there anyway to have two fully functional forms on the same page that both respond to the same route? This is my method for reference:
const express = require('express')
const bcrypt = require('bcrypt');
const passport = require('passport');
const router = express.Router()
const app = express()
const User = require('../models/User')
router.get('/', async (req, res) => {
res.render('pages/account', {
pageQuery: "Account"
});
// const allUsers = await User.find({})
// console.log(allUsers)
// User.remove({}, function(err) {
// console.log('collection removed')
// });
});
router.post('/', async (req, res) => {
let name = req.body.userNameSignUp
let password = req.body.userPasswordSignUp
let passwordConfirm = req.body.userPasswordSignUpConfirm
const hashedPassword = await bcrypt.hash(password, 10);
const newUser = new User({
userName: name,
userPassword: hashedPassword
});
if (!name || !password) {
res.render('pages/account', {
errorMessage: "*Please fill out all the fields",
pageQuery: "Account"
});
} else if (password !== passwordConfirm) {
res.render('pages/account', {
errorMessage: "*Passwords do not match",
pageQuery: "Account"
});
} else {
User.findOne({ userName: name })
.then(user => {
if (user) {
res.render('pages/account', {
errorMessage: "*Username Is Already In Use",
pageQuery: "Account"
});
}
})
}
try {
await newUser.save()
res.redirect('/account')
} catch (e) {
res.render('pages/account', {
errorMessage: "*Welp... The server's down. Come back later",
pageQuery: "Account"
});
}
});
module.exports = router;
and my ejs view for the forms:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Cheese | Account</title>
<%- include('../partials/linkandsrc'); %>
<script src="js/signUpToggle.js" defer></script>
</head>
<body>
<%- include('../partials/header'); %>
<%- include('../partials/navigation'); %>
<section class="signInSec">
<div class="account-container">
<div class="user signInBx">
<div class="imgBx">
<img src="images/SignUp.jpg" alt="">
</div>
<div class="formBx">
<form action="/account" method="POST">
<h2>Sign Up</h2>
<%- include('../partials/errorMessage'); %>
<input type="text" name="userNameSignUp" placeholder="Username">
<input type="text" name="userPasswordSignUp" placeholder="Password">
<input type="text" name="userPasswordSignUpConfirm" placeholder="Confirm Password">
<input type="submit" value="Create Account">
<p class="signin">Already have an account ? <a href="#" onclick="toggleForm();">Sign In.</a></p>
</form>
</div>
</div>
<div class="user signUpBx">
<div class="formBx">
<form action="/account" method="POST">
<h2>Sign In</h2>
<%- include('../partials/errorMessage'); %>
<input type="text" name="userNameLogIn" placeholder="Username">
<input type="text" name="userPasswordLogIn" placeholder="Password">
<input type="submit" value="Login">
<p class="signin">Don't have an account ? <a href="#" onclick="toggleForm();">Sign Up.</a></p>
</form>
</div>
<div class="imgBx">
<img src="images/SignIn.jpg" alt="">
</div>
</div>
</div>
</section>
</body>
</html>
If you're sure you want to have the same route (/account
) handle both the sign-up and the sign-in, then one approach might be to use hidden input
fields.
You could place a hidden input in the sign-up form, with name formType
(call it whatever you want, this is just an example) and value signup
:
<form action="/account" method="POST">
<h2>Sign Up</h2>
<%- include('../partials/errorMessage'); %>
<input type="text" name="userNameSignUp" placeholder="Username">
<input type="text" name="userPasswordSignUp" placeholder="Password">
<input type="text" name="userPasswordSignUpConfirm" placeholder="Confirm Password">
<input type="hidden" name="formType" value="signup">
<input type="submit" value="Create Account">
<p class="signin">Already have an account ? <a href="#" onclick="toggleForm();">Sign In.</a></p>
</form>
and similarly in the sign-in form, with name formType
and value signin
:
<form action="/account" method="POST">
<h2>Sign In</h2>
<%- include('../partials/errorMessage'); %>
<input type="text" name="userNameLogIn" placeholder="Username">
<input type="text" name="userPasswordLogIn" placeholder="Password">
<input type="hidden" name="formType" value="signin">
<input type="submit" value="Login">
<p class="signin">Don't have an account ? <a href="#" onclick="toggleForm();">Sign Up.</a></p>
</form>
Then, in your route handler, you could have some logic that differentiates a sign-up from a sign-in using the received formType
:
router.post('/', async (req, res) => {
if ('signup' === req.body.formType) {
// Server-sided sign-up logic can go here...
} else if ('signin' === req.body.formType) {
// Server-sided sign-in logic can go here....
} else {
// Something/someone has submitted an invalid form?
}
}