Ошибка проверки Joi, из какого поля показывать ошибку рядом с ним в пользовательском интерфейсе - PullRequest
1 голос
/ 02 февраля 2020

Мне нужно использовать библиотеку проверки Joi для проверки входных данных API и отправки данных.

Я сказал, что создал схему следующим образом:

import Joi from '@hapi/joi'

const eventSchema = Joi.object({
  title: Joi.string()
    .min(7)
    .max(50)
    .required()
    .error(() => Error('Event title has to be least 7 and max 50 characters.')),

  description: Joi.string()
    .min(10)
    .max(400)
    .required()
    .error(() => Error('Event description has to be least 10 and max 400 characters.')),

  place: Joi.string()
    .min(6)
    .max(40)
    .required()
    .error(() => Error('Event place has to be least 6 and max 40 characters.'))
})
export default eventSchema

Когда я проверяю это Я получаю ошибку проверки, как и ожидалось. Проблема в том, что я не знаю, какое поле действительно вызвало ошибку. Я хотел знать это, потому что я хочу точно показать ошибку рядом с тем полем, которое вызвало ошибку, а не просто общее сообщение проверки c, отображаемое в верхней части формы.

const isValid = eventSchema.validate()

if (isValid.error) {
  const fieldNameWhichCauseError = ???

  return {
   errors: { [fieldNameWhichCauseError]: isValid.error.message }
  }
}

// Everything looks good save to db
// ...etc.

Приведенный выше код имеет Теперь способ узнать имя поля в fieldNameWhichCauseError = ??? . Может кто-нибудь, пожалуйста, помогите мне? Я не видел, чтобы кто-нибудь делал такой сценарий. Я также не нашел в документах. У меня так много схем и проверок на месте, и это действительно мешает мне показывать ошибку в нужном месте пользовательского интерфейса.

Ответы [ 2 ]

1 голос
/ 02 февраля 2020

Я понял это сам. Когда-нибудь это может помочь кому-то искать здесь.

Сначала я бы создал собственный объект ValidationError.

class ValidationError extends Error {
   constructor(message, fieldName) {
     super(message)
     this.fieldName = fieldName
   }
}

Теперь используйте этот класс в приведенном выше коде, размещенном в Вопросе. Используйте ValidationError вместо класса Error, а также передайте ему имя поля. Пример

const eventSchema = Joi.object({
  title: Joi.string()
    .min(7)
    .max(50)
    .required()
    .error(() => new ValidationError('Event title has to be least 7 and max 50 characters.', 'title'))
})

Не забудьте использовать new при использовании пользовательского класса. Проверяющий код может получить значение error.fieldName из переданного объекта ошибки.

Надеюсь, это правильный подход. Если есть лучший подход, пожалуйста, напишите, я приму его в качестве ответа.

0 голосов
/ 02 февраля 2020

Я думаю, что есть лучший способ добиться этого, так как выкидывать ошибку не рекомендуется. (https://github.com/hapijs/joi/blob/master/API.md#anyerrorerr)

Вы должны использовать any.messages (https://github.com/hapijs/joi/blob/master/API.md#anymessagesmessages) и добавлять свои собственные сообщения. Как вы их определяете, вы всегда получаете сообщение об ошибке одного типа, даже если пользователь ничего не указал. Также использование переопределений ошибок abortEarly параметров. Это означает, что вы не получите все сообщения, только первое.

Использование сообщений может быть сделано следующим образом.

const Joi = require('@hapi/joi');
const eventSchema = Joi.object({
    title: Joi.string()
        .min(7)
        .max(50)
        .required()
        .messages({
            'string.base': `"description" should be a type of 'text'`,
            'string.min': '"title" has to be least {#limit} characters.',
            'string.max': '"title" has to be max {#limit} characters.',
            'any.required': `"title" is a required field`,
        }),

    description: Joi.string()
        .min(10)
        .max(400)
        .required()
        .messages({
            'string.base': `"description" should be a type of 'text'`,
            'string.min': '"description" has to be least {#limit} characters.',
            'string.max': '"description" has to be max {#limit} characters.',
            'any.required': `"description" is a required field`
        }),

    place: Joi.string()
        .min(6)
        .max(40)
        .required()
        .messages({
            'string.base': `"place" should be a type of 'text'`,
            'string.min': '"place" has to be least {#limit} characters.',
            'string.max': '"place" has to be max {#limit} characters.',
            'any.required': `"place" is a required field`
        })
});

eventSchema.validate({
    "title": "hi"
}, {
    "abortEarly": false
});

...