Почему req.body пуст при публикации формы в quiz.ejs

приложение.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.info('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.info(`Server is running on port ${PORT}`);
});

маршруты/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.info(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>

Схема модели викторины

const mongoose = require('mongoose');

const quizSchema = new mongoose.Schema({
    question: String,
    options: [String],
    answer: String
});
module.exports = mongoose.model('Quiz', quizSchema);

Проблема В quiz.ejs, почему форма дает мне пустой объект в консоли, я правильно указываю имя и значение ввода после отправки формы и перехожу к маршрутизатору отправки, который я упоминаю в приведенном выше коде, и я console.info(req.body), он дает мне пустой объект. Я создаю веб-сайт приложения для викторины, и когда я даю все ответы на вопросы и завершаю отправку, он не показывает оценку, и когда я вижу весь свой код, я вижу req, body дает мне пустой объект, почему я также использую промежуточное программное обеспечение чтобы проанализировать сообщение, тогда почему оно дает мне пустой объект

🤔 А знаете ли вы, что...
JavaScript имеет множество встроенных объектов, таких как Array, Date и Math.


1
82
1

Ответ:

Решено

Проблема связана с функцией JavaScript checkAnswer: она устанавливает для каждого параметра значение disabled, а отключенные параметры не отправляют значения при отправке формы, поэтому вы получаете пустой объект на сервере.

Итак, вам нужно изменить свою логику и предотвратить отключение опции, которая должна отправлять данные.

Например, вы можете отключить неправильные и непроверенные параметры, а к правильному добавить функцию, которая предотвратит его последующий выбор, и тем самым разрешить его отправку вместе с формой, однако он не будет стилизован как disabled, но вы можете оформить его так, чтобы оно выглядело как disabled, например, уменьшить непрозрачность, удалить события указателя или что-то подобное.

Попробуйте этот код:

  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";
  }