app.js
const express = require('express');
const mongoose = require('mongoose');
const path=require('path');
const app = express();
// Connect to MongoDB
async function main(){
await mongoose.connect('mongodb://localhost:27017/quizApp');
console.log('db is connected');
}
main();
// Middleware
app.set('view engine', 'ejs');
app.set('views',path.join(__dirname,'/views'));
app.use(express.static(path.join(__dirname,'public')));
app.use(express.urlencoded({extended:true}));
app.use(express.json());
// Routes
const indexRoutes = require('./routes/index');
app.use('/', indexRoutes);
// Start server
const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
routes/index.js
const express = require('express');
const router = express.Router();
const Quiz = require('../models/quiz');
router.get('/', async (req, res) => {
const quizzes = await Quiz.find({});
res.render('quiz', { quizzes });
});
router.post('/submit', async (req, res) => {
const answers = req.body;
console.log(req.body);
let score = 0;
const quizzes = await Quiz.find({});
quizzes.forEach(quiz => {
if (answers[quiz._id] === quiz.answer) {
score++;
}
});
res.render('result', { score, total: quizzes.length });
});
module.exports = router;
quiz.ejs
<form id="quizForm" action="http://localhost:3000/submit" method="post">
<% quizzes.forEach((quiz, index) => { %>
<div
class="question-container"
id="question-<%= index %>"
style="display: none"
>
<p class="lead"><%= quiz.question %></p>
<% quiz.options.forEach(option => { %>
<div class="custom-control custom-radio">
<input
type="radio"
id="<%= 'question' + index + option %>"
name="<%= quiz._id %>"
value="<%= option %>"
class="custom-control-input"
onclick="checkAnswer('<%= quiz.answer %>', this)"
/>
<label
class="custom-control-label"
for="<%= 'question' + index + option %>"
><%= option %></label
>
</div>
<% }) %>
</div>
<% }) %>
<button
type="button"
class="btn btn-secondary"
id="prevBtn"
onclick="changeQuestion(-1)"
disabled
>
Previous
</button>
<button
type="button"
class="btn btn-secondary"
id="nextBtn"
onclick="changeQuestion(1)"
style="display: none"
>
Next
</button>
<button
type="submit"
class="btn btn-primary"
id="submitBtn"
style="display: none"
>
Submit
</button>
</form>
<script>
const questions = document.querySelectorAll(".question-container");
let currentQuestionIndex = 0;
function showQuestion(index) {
questions.forEach((question, i) => {
question.style.display = i === index ? "block" : "none";
});
document.getElementById("questionNumber").textContent =
`${index + 1}/${questions.length}`;
document.getElementById("prevBtn").disabled = index === 0;
document.getElementById("nextBtn").style.display =
index === questions.length - 1 ? "none" : "inline-block";
document.getElementById("submitBtn").style.display =
index === questions.length - 1 ? "inline-block" : "none";
}
function changeQuestion(direction) {
currentQuestionIndex += direction;
showQuestion(currentQuestionIndex);
}
function checkAnswer(correctAnswer, selectedOption) {
const questionContainer = selectedOption.closest(".question-container");
const options = questionContainer.querySelectorAll(".custom-control-input");
options.forEach((option) => {
const label = questionContainer.querySelector(
`label[for="${option.id}"]`,
);
if (option.value === correctAnswer) {
label.style.backgroundColor = "green";
} else if (option.checked) {
label.style.backgroundColor = "red";
}
option.disabled = true;
});
document.getElementById("nextBtn").style.display = "inline-block";
}
// Initial display of the first question
showQuestion(currentQuestionIndex);
</script>
Quiz model Schema
const mongoose = require('mongoose');
const quizSchema = new mongoose.Schema({
question: String,
options: [String],
answer: String
});
module.exports = mongoose.model('Quiz', quizSchema);
Problem In quiz.ejs why form give me empty object in console I proper give name and value of input after submit the form and goes to the submit router I mention in above code and I console.log(req.body) it give me a empty object. I make a quiz app website and when i give the all the answers of the questions and final submit then it not show the score it and when i saw all my code then I see req,body give me empty object why i also use the middlewares to parse the post then why it give me empty object
The problem is with JavaScript checkAnswer
function: it sets every option to disabled
, and disabled options don't send values when form is submitted, which is why you get empty object on the server.
So, you need to change your logic, and prevent having disabled option which should send data.
For example, you could disable options that are not correct and not checked, and to the correct one add a function which will prevent selecting it afterwards, and by that enable it being submitted along with the form, however, it would not be styled as disabled
, but you could style it to appear as disabled
, for example, reduce opacity, remove pointer events or similar.
Try this code:
if (option.value === correctAnswer) {
label.style.backgroundColor = "green";
// leave it enabled, but prevent later selections
option.onclick = () => false;
// style it a bit to look like disabled
option.style.opacity = ".5";
option.style.pointerEvents = "none";
} else {
// disabled wrong and unchecked
option.disabled = true;
// style wrong
if (option.checked) label.style.backgroundColor = "red";
}