使用Yup+Formik验证对象数组



我必须使用Yup+Formik验证对象数组。

我目前的Yup:模式

Yup.object().shape({
Enderecos: Yup.array()
.of(
Yup.object().shape({
BairroId: Yup.number()
.required('Campo obrigatório'),
CtbEndCadMunicipio: Yup.number()
.required('Campo obrigatório'),
CtbEndTipo: Yup.number()
.required('Campo obrigatório'),
LograId: Yup.number()
.required('Campo obrigatório'),
MunId: Yup.number(),
CtbEndComplemento: Yup.string()
.min(defaultMinimumCharacters, `Minimo de ${defaultMinimumCharacters} caracteres`)
.max(200, `Máximo de ${200} caracteres`)
.required('Campo obrigatório'),
CtbEndNumero: Yup.string()
.min(defaultMinimumCharacters, `Minimo de ${defaultMinimumCharacters} caracteres`)
.max(10, `Máximo de ${10} caracteres`)
.required('Campo obrigatório'),
CtbEndCep: Yup.string()
.min(defaultMinimumCharacters, `Minimo de ${defaultMinimumCharacters} caracteres`)
.max(8, `Máximo de ${8} caracteres`)
.required('Campo obrigatório'),
})
)}),

我在表单HTML元素中使用formik,所以我显示如下字段:

<div className='fv-row me-4 mb-7 w-100'>
<label className='required fw-bold fs-6 mb-2'>CEP</label>
<input
placeholder='CEP'
{...values?.getFieldProps('Enderecos[0].CtbEndCep')}
type='text'
maxLength={8}
name='Enderecos[0].CtbEndCep'
className={clsx(
'form-control form-control-solid mb-3 mb-lg-0',
{ 'is-invalid': values?.touched.CtbEndCep && values?.errors.CtbEndCep },
{
'is-valid': values?.touched.CtbEndCep && !values?.errors.CtbEndCep,
}
)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => values?.setFieldValue('Enderecos[0].CtbEndCep', e.target.value)}
/>
{values?.touched.CtbEndCep && values?.errors.CtbEndCep && (
<div className='fv-plugins-message-container'>
<div className='fv-help-block'>
<span role='alert'>{values?.errors.CtbEndCep}</span>
</div>
</div>
)}
</div>

问题是,如果我想触摸数组中的一个字段,比如这个values?.touched.Enderecos[0].CtbEndCep,我会得到未定义的错误,这是有道理的,因为第一次呈现表单时,触摸的对象是空的。

我的疑问是,它是否有这样的工作方式,我在这里能做什么?我想在这里看到CSS/样式验证。当字段充满燃料时为绿色,当输入字段的值出现问题时为红色。

我设法解决了我的问题,如下所示:

{values?.getFieldProps('Enderecos').value?.map((item: any, index: number) => (
<div className='fv-row me-4 mb-7 w-100'>
<label className='required fw-bold fs-6 mb-2'>CEP</label>
<input
placeholder='CEP'
{...values?.getFieldProps('Enderecos[0].CtbEndCep')}
type='text'
maxLength={8}
name='Enderecos[0].CtbEndCep'
className={clsx(
'form-control form-control-solid mb-3 mb-lg-0',
{ 'is-invalid': values?.touched.Enderecos?.[index]?.CtbEndCep && values?.errors.Enderecos?.[index]?.CtbEndCep },
{
'is-valid': values?.touched.Enderecos?.[index]?.CtbEndCep && !values?.errors.Enderecos?.[index]?.CtbEndCep,
}
)}
onChange={(e: React.ChangeEvent<HTMLInputElement>) => values?.setFieldValue('Enderecos[0].CtbEndCep', e.target.value)}
onBlur={() => onBlurBuscaCEP(0)}
/>
{values?.touched.Enderecos?.[index]?.CtbEndCep && values?.errors.Enderecos?.[index]?.CtbEndCep && (
<div className='fv-plugins-message-container'>
<div className='fv-help-block'>
<span role='alert'>{values?.errors.Enderecos?.[index]?.CtbEndCep}</span>
</div>
</div>
)}
</div>
))}

我在values?.getFieldProps('Enderecos').value中做了一个映射,并使用.map函数中的index道具作为我要验证的当前数组和字段的索引,效果很好。

最新更新