ManInTheBox
ManInTheBox

Reputation: 174

Custom (user-friendly) ValidatorError message

I'm really new to mongoose, so I was wondering if there is some way to set custom error message instead of default one like Validator "required" failed for path password.

I would like to set something like Password is required. which is more user-friendly.

I wrote some custom validators and set type property with this user-friendly error message, but I'm not sure type is right placeholder for error message. also there is no way to set custom message on predefined validators like min, max, required, enum...

One solution is to check every time type property of error thrown and manually assign error message, but think that's validator's job:

save model
    if error
        check error type (eg. "required")
        assign fancy error message (eg. "Password is required.")

This obviously isn't ideal solution.

I looked at express-form and node-validator but still want to use mongoose validation feature.

Upvotes: 11

Views: 5426

Answers (2)

jdnichollsc
jdnichollsc

Reputation: 1569

If you need get the first error message, see the following example:

var firstError = err.errors[Object.keys(err.errors)[0]];
return res.status(500).send(firstError.message);

Regards, Nicholls

Upvotes: 0

clarkf
clarkf

Reputation: 3052

I generally use a helper function for such things. Just mocked this one up to be a little more general than then ones I use. This guy will take all of the "default" validators (required, min, max, etc.) and make their messages a little prettier (according to the messages object below), and extract just the message that you passed in your validator for custom validations.

function errorHelper(err, cb) {
    //If it isn't a mongoose-validation error, just throw it.
    if (err.name !== 'ValidationError') return cb(err);
    var messages = {
        'required': "%s is required.",
        'min': "%s below minimum.",
        'max': "%s above maximum.",
        'enum': "%s not an allowed value."
    };

    //A validationerror can contain more than one error.
    var errors = [];

    //Loop over the errors object of the Validation Error
    Object.keys(err.errors).forEach(function (field) {
        var eObj = err.errors[field];

        //If we don't have a message for `type`, just push the error through
        if (!messages.hasOwnProperty(eObj.type)) errors.push(eObj.type);

        //Otherwise, use util.format to format the message, and passing the path
        else errors.push(require('util').format(messages[eObj.type], eObj.path));
    });

    return cb(errors);
}

And it can be used like this (express router example):

function (req, res, next) {
    //generate `user` here
    user.save(function (err) {
        //If we have an error, call the helper, return, and pass it `next`
        //to pass the "user-friendly" errors to
        if (err) return errorHelper(err, next);
    }
}

Before:

{ message: 'Validation failed',
  name: 'ValidationError',
  errors: 
   { username: 
      { message: 'Validator "required" failed for path username',
        name: 'ValidatorError',
        path: 'username',
        type: 'required' },
     state: 
      { message: 'Validator "enum" failed for path state',
        name: 'ValidatorError',
        path: 'state',
        type: 'enum' },
     email: 
      { message: 'Validator "custom validator here" failed for path email',
        name: 'ValidatorError',
        path: 'email',
        type: 'custom validator here' },
     age: 
      { message: 'Validator "min" failed for path age',
        name: 'ValidatorError',
        path: 'age',
        type: 'min' } } }

After:

[ 'username is required.',
  'state not an allowed value.',
  'custom validator here',
  'age below minimum.' ]

Edit: Snap, just realized this was a CoffeeScript question. Not being a CoffeeScript guy, I wouldn't really want to rewrite this in CS. You could always just require it as a js file into your CS?

Upvotes: 16

Related Questions