I have a validation that only validates its fields by checking if they are break its only rules, but it allows duplications inside the Array.
I want some sort of condition that won't allow duplicated values inside of it.
My object:
respostas: Yup.array()
.of(
Yup.object().shape({
nome: Yup.string()
.trim()
.max(1000, Messages.RESPOSTA_ENQUETE_TAMANHO_MAXIMO)
.required(Messages.CAMPO_OBRIGATORIO)
})
)
.required(Messages.RESPOSTA_QUANTIDADE_MINIMA)
For example, I would have an array like this: [aaa,bbb,aaa] allowed, but I don't want this duplication.
To validate this you can write your own .test(). You can add the following test to the Yup object.
.test("Unique", "Values need te be unique", values => {
return (new Set(values)).size === values.length;
})
The error will be added to the object in general, not at the specific field.
const { addOrEdit, recordForEdit, fabricTypeList } = props;
const duplicateNameCheck = (list, value) => {
for (var i = 0; i < list.length; i++) {
if (value === list[i].name) {
return false;
} else {
return true;
}
}
};
const validationSchema = yup.object().shape({
name: yup
.string()
.required("Name is required")
.test("Unique", "Name needs te be unique", (values) => {
return duplicateNameCheck(fabricTypeList, values);
}),
});
const formik = useFormik({
initialValues: initialValues,
validationSchema: validationSchema,
onSubmit: (values, { setSubmitting, resetForm }) => {
setSubmitting(true);
addOrEdit(values, resetForm, setSubmitting);
},
});
Related
I'm using a hook that fills in my inputs automatically, according to the zip code the user enters. Then the user's address, street, etc are filled in automatically.
However, for the input to be filled in automatically, the component is re-rendering.
As my form is a modal it opens and closes again because of rendering. I need to make the user fill in the zip code, the inputs are filled in real time.
Can you help me with this?
useCEP Hook:
import { useState } from 'react'
import { api } from 'services/apiClient'
interface Cep {
bairro: string
logradouro: string
localidade: string
uf: string
}
export function useCep() {
const [checkCep, setCheckCep] = useState<Cep>()
const getCEP = async (e) => {
const cep = e.target.value.replace(/\D/g, '')
try {
const { data } = await api.get(`https://viacep.com.br/ws/${cep}/json/`)
setCheckCep(data)
} catch (err) {
console.log(err)
}
}
return { checkCep, getCEP }
}
Component:
const { control, formState, register, reset } = useFormContext()
const { checkCep, getCEP } = useCep()
useEffect(() => {
reset({
responsible: [
{
address: checkCep?.logradouro,
district: checkCep?.bairro,
city: checkCep?.localidade,
state: checkCep?.uf,
name: '',
email: '',
student_name: [],
cep: '',
residence: '',
telephone: '',
sex: ''
}
]
})
}, [checkCep])
<Input
name="cep"
type="number"
label="Cep"
{...register(`responsible.${index}.cep`)}
error={errors?.responsible?.[index]?.cep}
onBlur={(e) => getCEP(e)}
/>
{...}
Maybe you can try to use the setValue method instead of reset as it will reset the form.
https://react-hook-form.com/api/useform/setvalue
OtherResonChage only required if ReasonChange array include "Other" in it else that field is not required
export const formikValues = {
reasonChangeJob: [],
otherReasonChangeJob: "",
}
export const questionnaireSchema = Yup.object({
reasonChangeJob: Yup.array()
.required("req")
.min(1, "min q"),
otherReasonChangeJob: Yup.string().when(
"reasonChangeJob",
(reasonChangeJob) => {
if (reasonChangeJob.include("other")) {
return Yup.string().required(" req");
}
}
)
});
I'm using include instead of includes and this is the better way to handle conditional validations
otherReasonChangeJob: Yup.string().when("reasonChangeJob", {
is: (reasonChangeJob) => reasonChangeJob.includes("other"),
then: Yup.string().required("Require please"),
}),
I use react-hook-form and yup-validation. An array with custom names comes to me from the backend. Validation doesn't work for me. What am I doing
export const createValidationSchema = (arr) => {
const validationObject = {};
arr?.forEach(({name}) => {
validationObject[name] = string().required("Required field")
});
return object().shape({
editFields: array()
.of(object().shape(validationObject))
.required("Required field")
});
};
const { control, register, handleSubmit, formState: { errors, isValid } } = useForm<Form>({
resolver: yupResolver(createValidationSchema(documentDetail?.template?.items)),
mode: "onBlur"
});
const { fields, append } = useFieldArray<Form>({
control,
name: "editFields",
});
below in JSX:
{fields?.map(({ name, title, type, id }) => (
{type === "STRING" && (
<InputField
validationType="underlineText"
{...register(name)}
required
/>
)}
)
but errors always empty. What am I doing wrong?
My mistake. In validationObject I have an object, and in the schema I assigned it as an array
I was trying to populate the initialValue of my formik form with its hoc data onClick.
Clearing the form back to its first initialValue (initValues) when the reForm() is used does'nt work and it always goes back to the value from the prop.
parent:
const [contactData, setContactData] = useState();
.
..
....
<First userData={contactData}/>
<Second userData={setContactData}/>
child:
function FirstComponent({userData}) {
const [isUpdate, setUpdate] = useState(false);
const initValues = {
id:'',
email: '',
name: '',
contact: ''
};
useEffect(() => {
// setContactData(userData)
userData!==undefined ? setUpdate(true) : setUpdate(false);
console.log("from form: ", userData)
}, [userData]);
const formik = useFormik({
enableReinitialize: true,
validationSchema: FormSchema,
initialValues: userData || initValues,
onSubmit: (values) => {
// same shape as initial values
console.log("the Data ", userData)
console.log("onsubmit ", values);
}
})
const resForm = () => {
formik.initialValues = {initValues};
console.log("prop ", userData)
console.log("formik values ",formik.initialValues)
formik.resetForm();
}
Replacing the initialValues with initValues in formik.resetForm() seems to work, but it makes the form reinitialize back with the userData prop - function FormComponent({userData})
partially fixed..
just modified the formik.resetForm() in resForm() to
formik.resetForm({
values:initValues
});
but the prop (userData) from parent still persists when console logged in resForm()
I'm working on a ReactJS project. I'm learning to use Yup for Validation with FormIk . The following code works fine:
const ValidationSchema = Yup.object().shape({
paymentCardName: Yup.string().required(s.validation.paymentCardName.required),
paymentCardNumber: Yup.string()
/*
.test(
"test-num",
"Requires 16 digits",
(value) => !isEmpty(value) && value.replace(/\s/g, "").length === 16
)
*/
.test(
"test-ctype",
"We do not accept this card type",
(value) => getCardType(value).length > 0
)
.required(),
But the moment I uncomment the test-num the developer tools complain about an uncaught promise:
How do I get Yup to give me a different error string based on the validation failure that I detect?
You can use the addMethod method to create two custom validation methods like this.
Yup.addMethod(Yup.string, "creditCardType", function (errorMessage) {
return this.test(`test-card-type`, errorMessage, function (value) {
const { path, createError } = this;
return (
getCardType(value).length > 0 ||
createError({ path, message: errorMessage })
);
});
});
Yup.addMethod(Yup.string, "creditCardLength", function (errorMessage) {
return this.test(`test-card-length`, errorMessage, function (value) {
const { path, createError } = this;
return (
(value && value.length === 16) ||
createError({ path, message: errorMessage })
);
});
});
const validationSchema = Yup.object().shape({
creditCard: Yup.string()
.creditCardType("We do not accept this card type")
.creditCardLength('Too short')
.required("Required"),
});