简体   繁体   English

Joi 验证错误来自哪个字段在 UI 中显示错误

[英]Joi validation error from which field to show error next to it in UI

I have to use Joi validation library to validate in the API input and so send the output.我必须使用 Joi 验证库来验证 API 输入,然后发送输出。

I have say created a schema as follows:我说过创建了一个模式如下:

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

When I validate this, I get validation error as expected.当我验证这一点时,我得到了预期的验证错误。 The problem here is I do not know which field really caused error.这里的问题是我不知道哪个字段真正导致了错误。 I wanted to know this because I want exactly to show the error next to that field which caused the error instead of just generic validation message showing at the top of form.我想知道这一点,因为我想确切地显示导致错误的字段旁边的错误,而不仅仅是显示在表单顶部的通用验证消息。

const isValid = eventSchema.validate()

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

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

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

The above code has now way to know the field name in fieldNameWhichCauseError = ???上面的代码现在可以知道fieldNameWhichCauseError = ??? 中的字段名称. . Can somebody please help me?有人能帮帮我吗? I haven't seen anyone doing such scenario.我还没有看到有人做这样的场景。 I also didn't find in the docs.我也没有在文档中找到。 I have so many schemas and validations in place and this is something really blocking me to show the error at proper place in the UI.我有很多模式和验证,这真的阻止了我在 UI 中的适当位置显示错误。

I figured it out myself.我自己想通了。 Someday it might help someone searching here.有一天它可能会帮助某人在这里搜索。

First I would create a custom ValidationError object.首先,我将创建一个自定义 ValidationError 对象。

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

Now use this class in the above code posted in Question.现在在上面发布在问题中的代码中使用这个类。 Use ValidationError instead of Error class and also pass the field name to it.使用 ValidationError 而不是 Error 类,并将字段名称传递给它。 Example例子

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'))
})

Remember to use new while using custom class.记住在使用自定义类时使用new The code which validates can get error.fieldName value from the error object passed down.验证的代码可以从传递下来的错误对象中获取error.fieldName值。

I hope this is the correct approach.我希望这是正确的方法。 If there is better approach, please post I'll accept it as an answer.如果有更好的方法,请张贴我会接受它作为答案。

I think there is a better way to achieve this as throwing error is not recommended way to achieve this.我认为有更好的方法来实现这一点,因为不推荐使用抛出错误来实现这一点。 ( https://github.com/hapijs/joi/blob/master/API.md#anyerrorerr ) ( https://github.com/hapijs/joi/blob/master/API.md#anyerrorerr )

You should leverage any.messages ( https://github.com/hapijs/joi/blob/master/API.md#anymessagesmessages ) and add your custom messages.您应该利用any.messages ( https://github.com/hapijs/joi/blob/master/API.md#anymessagesmessages ) 并添加您的自定义消息。 The way you are defining them, you always get same type of error message even if user hasn't specified any thing.根据您定义它们的方式,即使用户没有指定任何内容,您也总是会收到相同类型的错误消息。 Also using error overrides abortEarly options.还使用错误覆盖abortEarly选项。 That means you will not get all the messages, just the first one.这意味着您不会收到所有消息,只会收到第一条消息。

Using messages can be done like this.可以像这样使用消息。

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

Joi 17.4 上validate()返回的error有一个名为details的属性,您可以从中访问有关这些错误的详细信息(例如这些错误属于哪些字段)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM