Cuando se esta desarrollando algún proyecto utilizando la librería se consulta en la documentación de esa librería con el objetivo de saber como se puede utilizar. Formik es una de las librerías más usadas para poder manejar los formularios en proyectos web. Ademas, se encarga de manejar las validaciones y el evento submit. Esta libería también cuenta para manejo de formularios, con inputs ya integrados con Formik y hooks en caso que se no se quiera usar dichos inputs.
En la documentación con esa librería se cuentan con ejemplos para varíos casos usando sus inputs personalizados. Uno de ellos son objetos anidados demostrando soporte para este tipo de objetos. Si bien se evidencia el soporte de objetos anidados en caso de querer usar los hooks con los que cuenta la librería, no existen ejemplos. Por lo que aquí daremos apoyo a la duda de como se pueden integrar objetos anidados usando solo los hooks de la libería.
Todo el código utilizado para este tutorial lo podrás entrar aquí: useFormik.
Para quien quiera una demo funcional: useFormik demo
Valores Iniciales
Para empezar aclarando que en este ejemplo utilizaremos el hook useFormik pero, el ejemplo se puede aplicar con cualquier hook de la libería. Primero declaremos el objeto inicial con el que estaremos trabajando junto a su tipado.
interface UserInfo {
personal: {
name: string;
lastName: string;
age: number;
};
location: {
address: string;
country: string;
};
}
const initialValues: UserInfo = {
personal: {
name: "",
lastName: "",
age: 0,
},
location: {
address: "",
country: "",
},
};
También inicializamos los validadores que utilizaremos para nuestro formulario. Para efectos de este ejemplo utilizaremos la libería de validadores Yup para facilitar validaciones.
const validationSchema = yup.object().shape({
personal: yup.object().shape({
name: yup.string().required("Name is required"),
lastName: yup.string().required("Last name is required"),
age: yup
.number()
.required("Age is required")
.min(1, "You should have at least 1 year"),
}),
location: yup.object().shape({
address: yup.string().required("Address is required"),
country: yup.string().required("Country is required"),
}),
});
Formik
Inicializamos el formik que vamos a utilizar para manejar nuestro formulario.
const formik = useFormik<UserInfo>({
initialValues,
validationSchema,
onSubmit: (values, { resetForm }) => {
console.log("values: ", values);
toast.current?.show({
severity: "success",
summary: "Form submitted",
detail: "The form was submitted",
});
resetForm();
},
});
Con esto procederemos a explicar los inputs donde encontraremos la clave para utilizar objetos anidados
Inputs
Para evitar repetir código crearemos unos inputs especiales para que puedan ser útilizado en nuestro formulario de ejemplo. Aqui expongo uno de los tres tipos de input que crearemos para este formulario. Los otros dos los pueden encontrar en la demo o en el código subido al repositorio.
<InputText
id={name}
name={name}
value={get(formik.values, name)}
onChange={formik.handleChange}
onBlur={formik.handleBlur}
className={classNames({ "p-invalid": isInvalid(name, formik) })}
/>
En esta clase de input podemos ver que la forma de detectar los cambios en el input es la misma forma que con los campos no anidados. Para obtener el valor solo basta con primero acceder al objeto anidado y luego al campo especifico. Formik para poder manejar los campos de objetos anidados y poder cambiarlos utiliza la siguiente sintaxis: "ob1.ob2.....objn.campo". Para poder acceder a su información solo basta con utilizar una función que permita con solo dar el objeto formik.values y el campo como la sintaxis descrita arriba traer el valor en cuestión. En este caso utilizamos la función get de la libería lodash para poder cumplir con dicha función.
Resultado
Luego de ver las partes que componen el formulario tendremos como resultado algo similar:
function App() {
const toast = useRef<Toast>(null);
const formik = useFormik<UserInfo>({
initialValues,
validationSchema,
onSubmit: (values, { resetForm }) => {
console.log("values: ", values);
toast.current?.show({
severity: "success",
summary: "Form submitted",
detail: "The form was submitted",
});
resetForm();
},
});
return (
<div className="App">
<Toast ref={toast} />
<form
className="w-full h-full flex flex-column align-items-center"
onSubmit={formik.handleSubmit}
>
<h1>useFormik with nested objects</h1>
<h2>Personal Info</h2>
<div className="flex flex-column gap-4">
<MInputText
name="personal.name"
label="Name"
formik={formik}
/>
<MInputText
name="personal.lastName"
label="Last name"
formik={formik}
/>
<MInputNumber
name="personal.age"
label="Age"
formik={formik}
/>
</div>
<h2>Address Info</h2>
<div className="flex flex-column gap-4">
<MInputText
name="location.address"
label="Address"
formik={formik}
/>
<MDropdown
name="location.country"
label="Country"
formik={formik}
options={countries}
/>
</div>
<Button
label="Send Form"
type="submit"
className="mt-4"
/>
</form>
</div>
);
}
Por lo que usar objetos anidados con los hooks de useFormik no es complicado. Solo es de recordar que para editar los campos se utiliza la notación obj.campo y utilizar una función auxiliar para obtener los valores.
Bibliografía
Formik: https://formik.org/docs/overview
Top comments (0)