Reputation: 119
I must validate an array of objects using Yup + Formik.
My current schema of 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'),
})
)}),
I'm using formik along form HTML element, so I display the fields like this:
<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>
The problem is if I want do touched a field in the array, like this values?.touched.Enderecos[0].CtbEndCep
, I got error undefined, which make sense, since the touched object is empty when rendering the form for the first time.
My doubt is if it has a way to work like that and what can I do here? I want to see here the CSS/styles validations. The green, when the field is fuel up and red when there is something wrong with the value inputed into the field.
Upvotes: 1
Views: 2164
Reputation: 119
I managed to solved my issue like this:
{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>
))}
I do a map in the values?.getFieldProps('Enderecos').value
and use the index
props from .map
function as index of the current array and field I want validate, this worked well.
Upvotes: 1