2

I have set up Mongoose custom validation with errors and would like to display these error messages in React. I am unfortunately unable to retrieve the error messages. I have tried looking for solutions, but am unfortunately still having trouble.

My code is as follows:

Server-side:

- dataModel.js

const mongoose = require("mongoose");
const uniqueValidator = require("mongoose-unique-validator");
const moment = require("moment");

const dataSchema = mongoose.Schema(
  {
    name: {
      type: String,
      required: [true, "Name is required."],
      validate: {
        validator: function (name) {
          return /^[a-zA-Z]+$/.test(name);
        },
        message: "Only alphabetic characters allowed.",
      },
    },
    surname: {
      type: String,
      required: [true, "Surname is required."],
      validate: {
        validator: function (surname) {
          return /^[a-zA-Z]+$/.test(surname);
        },
        message: "Only alphabetic characters allowed.",
      },
    },
    idNumber: {
      type: String,
      required: [true, "ID Number is required."],
      unique: true,
      validate: [
        {
          validator: function (idNumber) {
            return idNumber.toString().length === 13;
          },
          message: (idNumber) =>
            `ID Number Must Have 13 Numbers. You entered ${
              idNumber.value
            }, which is ${idNumber.value.toString().length} numbers long.`,
        },
        {
          validator: function (idNumber) {
            return !isNaN(parseFloat(idNumber)) && isFinite(idNumber);
          },
          message: (idNumber) =>
            `ID Number Can Only Contain Number Values. You entered ${idNumber.value}.`,
        },
      ],
    },
    dateOfBirth: {
      type: String,
      required: [true, "Date of Birth is required."],
      validate: {
        validator: function (dateOfBirth) {
          return moment(dateOfBirth, "DD/MM/YYYY", true).isValid();
        },
        message: "Invalid Date of Birth Format. Expected DD/MM/YYYY.",
      },
    },
  },
  {
    timestamps: true,
  }
);

dataSchema.plugin(uniqueValidator, { message: "ID Number Already Exists." });

module.exports = mongoose.model("Data", dataSchema);

- dataController.js

exports.addController = async (req, res) => {
  const { firstName, surname, idNumber, dateOfBirth } = req.body;

  const newData = new Data({
    name: firstName,
    surname,
    idNumber,
    dateOfBirth,
  });

  try {
    await newData.save();
    res.send({ message: "Data Added Successfully" });
  } catch (error) {
    if (error.name === "ValidationError") {
      let errors = {};

      Object.keys(error.errors).forEach((key) => {
        errors[key] = error.errors[key].message;
      });
      
      console.log(errors)

      return res.status(400).send(errors);
    }
    res.status(500).send("Something went wrong");
  }
};

Output - console.log:

Screenshot - Console - Back

Client-side:

- dataForm.js

  const addData = async () => {
    try {
      axios({
        url: "/data/add",
        method: "post",
        data: {
          firstName,
          surname,
          idNumber,
          dateOfBirth,
        },
        headers: {
          "Content-type": "application/json",
        },
      }).then(function (response) {
        alert(response.data.message);
        console.log(response.data.message);
      });
    } catch (error) {
      console.log(error);
      }
  };

Output - Console:

Screenshot - Console

Output - Postman (Initial):

{
  "message": [
    "Only alphabetic characters allowed.",
    "ID Number Can Only Contain Number Values. You entered 888888888888a."
  ],
  "error": {
    "errors": {
      "surname": {
        "name": "ValidatorError",
        "message": "Only alphabetic characters allowed.",
        "properties": {
          "message": "Only alphabetic characters allowed.",
          "type": "user defined",
          "path": "surname",
          "value": "Bösiger"
        },
        "kind": "user defined",
        "path": "surname",
        "value": "Bösiger"
      },
      "idNumber": {
        "name": "ValidatorError",
        "message": "ID Number Can Only Contain Number Values. You entered 888888888888a.",
        "properties": {
          "message": "ID Number Can Only Contain Number Values. You entered 888888888888a.",
          "type": "user defined",
          "path": "idNumber",
          "value": "888888888888a"
        },
        "kind": "user defined",
        "path": "idNumber",
        "value": "888888888888a"
      }
    },
    "_message": "Data validation failed",
    "name": "ValidationError",
    "message": "Data validation failed: surname: Only alphabetic characters allowed., idNumber: ID Number Can Only Contain Number Values. You entered 888888888888a."
  }
}

Output - Postman (Current):

Screenshot - Postman

I would appreciate any help that anyone is willing to offer.

  • try with `console.log(error.response);` in your axios req – cmgchess Jan 29 '22 at 22:15
  • 1
    https://stackoverflow.com/questions/49967779/axios-handling-errors/60825383#60825383 – cmgchess Jan 29 '22 at 22:17
  • Hi @cmgchess. Thank you for your messages. I have tried logging all of the following with no success: console.log(error); console.log(error.response); console.log(error.response.data); console.log(error.response.status); console.log(error.response.headers); console.log(error.request); console.log('Error', error.message); – Chanelle Bösiger Jan 30 '22 at 06:10
  • what did it show on console – cmgchess Jan 30 '22 at 06:37
  • @cmgchess None of the console.log()s provided any output except for the normal: (POST http://localhost:3000/data/add 400 (Bad Request)) and (bundle.js:2068 Uncaught (in promise) Error: Request failed with status code 400 at createError (bundle.js:2068:15) at settle (bundle.js:2335:12) at XMLHttpRequest.onloadend (bundle.js:1395:7)). – Chanelle Bösiger Jan 30 '22 at 07:19

1 Answers1

1

I have managed to sort the problem out and return and display the Mongoose validation errors on the React frontend.

I amended the React post method as follows:

const addData = async () => {
    try {
      let response = await axios({
        url: "http://localhost:8080/data/add",
        method: "post",
        data: {
          firstName,
          surname,
          idNumber,
          dateOfBirth,
        },
        headers: {
          "Content-type": "application/json",
        },
      })
      .then((response) => {
        alert(response.data.message);
      })
      .then(() => {
        window.location.reload();
      });
      alert(response.data.message);
    } catch (error) {
      alert(Object.values(error.response.data) + ".");
    }
  };

I had to format the method as the error code was not being reached and had to return and display the data using Object.values() as the responses were objects.

Thank you @cmgchess for pointing me in the right direction.