Creación de formularios
Enfoque recomendado
Creación de la estructura de carpetas
Cree una carpeta en pages/MyForm para el componente, por ejemplo MyForm, y agréguele los siguientes archivos:
pages/MyForm/availableValues.tspages/MyForm/MyForm.messages.tspages/MyForm/MyForm.module.scsspages/MyForm/MyForm.tsx
Creación del formulario
En el directorio MyForm, cree el archivo <form_name>.tsx, en este ejemplo: ./MyForm.tsx.
Este ejemplo contiene dos tipos diferentes de validaciones. Al nivel de entrada, se activa con cada cambio de valor y, al nivel del formulario, se activa con el envío del formulario.
import React, { useContext, useState } from 'react';
import { Grid, GridItem } from '@jutro/layout';
import { Button, Card, TextInput, NumberInput } from '@jutro/components';
import { useTranslator } from '@jutro/locale';
import { InlineNotification } from '@jutro/components';
import messages from './MyForm.messages';
export const MyForm = () => {
const translator = useTranslator();
// Manage all form inputs values
const [formValues, setFormValues] = useState({ text: null, number: null });
// Handle text input changes
const handleTextChange = (e, newValue) => {
setFormValues({ text: newValue, number: formValues.number });
};
// Handle number input changes: including validation
const handleNumberChange = (e, newValue) => {
setFormValues({ text: formValues.text, number: newValue });
if (!isNaN(newValue) && newValue >= min && newValue <= max) {
setNumberValidationMessages({});
} else {
setNumberValidationMessages({
error: [translator(messages.numberfieldValidationError)],
});
}
};
// Overall validation messages
const [validationMessages, setValidationMessages] = useState({});
// Control overall validation messages display
const [notification, setNotification] = useState({show: false, type: 'success'});
// Number input validation info
const [numberValidationMessages, setNumberValidationMessages] = useState({});
const max = 100;
const min = 0;
// Form validation method: check required field and number in range
const isFormValid = () => {
const textValid = formValues.text != null && formValues.text.trim() != '';
let errorMessages = [];
if (!textValid) {
errorMessages.push(translator(messages.formValidationErrorText));
}
const numberValid =
!isNaN(formValues.number) &&
formValues.number >= min &&
formValues.number <= max;
if (!numberValid) {
errorMessages.push(
translator(messages.formValidationErrorNumber, { min: min, max: max })
);
}
return { valid: textValid && numberValid, errorMessages: errorMessages };
};
// Method to be executed on form submission
const saveForm = () => {
const { valid, errorMessages } = isFormValid();
if (valid) {
// Backend call could be performed here
setValidationMessages(messages.formSavedSuccesfully);
} else {
setValidationMessages(
translator(messages.formValidationError) + ' ' + errorMessages.join('. ')
);
}
setNotification({ show: true, type: valid ? 'success' : 'error' });
};
return (
<Card
title={translator(messages.formTitle)}
isPanel
fullWidth
>
<Grid
vgap="large"
columns={['1fr']}
style={{ width: '400px' }}
>
<GridItem>
<p>{translator(messages.formDescription)}</p>
</GridItem>
{notification.show && (
<GridItem>
<InlineNotification
message={validationMessages}
onClosed={() =>
setNotification({ show: false, type: 'success' })
}
type={notification.type == 'success' ? 'success' : 'error'}
/>
</GridItem>
)}
<GridItem>
<TextInput
label={translator(messages.textfieldLabel)}
secondaryLabel={translator(messages.textfieldSecondaryLabel)}
required
onChange={handleTextChange}
/>
<NumberInput
label={translator(messages.numberfieldLabel)}
secondaryLabel={translator(messages.numberfieldSecondaryLabel)}
min={min}
max={max}
onChange={handleNumberChange}
stateMessages={numberValidationMessages}
/>
</GridItem>
<GridItem>
<Button
onClick={saveForm}
label={translator(messages.submitTheForm)}
/>
</GridItem>
</Grid>
</Card>
);
};
Creación del archivo de mensajes (opcional)
No se recomienda que su formulario tenga texto codificado de forma rígida, por ello, quizás deba crear el archivo de mensajes para almacenar los strings de traducción:
import { defineMessages } from '@jutro/locale';
export default defineMessages({
formTitle: {
id: 'jutro-app.sample.form.title',
defaultMessage: 'My Sample Form',
},
formDescription: {
id: 'jutro-app.sample.form.description',
defaultMessage:
'Test the different form validation options: at field level when the user changes a value, on form submission...',
},
textfieldLabel: {
id: 'jutro-app.sample.form.textfield.label',
defaultMessage:
'Mandatory text',
},
textfieldSecondaryLabel: {
id: 'jutro-app.sample.form.textfield.secondarylabel',
defaultMessage:
'This is a mandatory text',
},
numberfieldLabel: {
id: 'jutro-app.sample.form.numberfield.label',
defaultMessage:
'Enter value',
},
numberfieldSecondaryLabel: {
id: 'jutro-app.sample.form.numberfield.secondarylabel',
defaultMessage:
'Min = 0. Max = 100',
},
numberfieldValidationError: {
id: 'jutro-app.sample.form.numberfield.validationerror',
defaultMessage:
'Value must be between 0 and 100',
},
submitTheForm: {
id: 'jutro-app.sample.form.submit',
defaultMessage: 'Submit',
description: 'Submit the form',
},
formSavedSuccesfully: {
id: 'jutro-app.sample.form..formSavedSuccesfully',
defaultMessage:
'You did a good job filling this form and it has been saved!',
},
formValidationError: {
id: 'jutro-app.sample.form.formValidationError',
defaultMessage:
'Invalid information: ',
},
formValidationErrorNumber: {
id: 'jutro-app.sample.form.numberError',
defaultMessage: 'Number input value must be between {min} and {max}',
},
formValidationErrorText: {
id: 'jutro-app.sample.form.textError',
defaultMessage: 'Mandatory text is required',
},
});
Consulte la sección Internacionalización para obtener más detalles.
Creación del archivo StyleSheet (opcional)
En caso de que necesite un estilo adicional, puede definirlo dentro del archivo ./MyForm.module.scss.
<FormName>.module.scss.Creación de los valores disponibles (opcional)
Puede crear un archivo para almacenar los valores disponibles para los campos del formulario, en lugar de codificarlos de forma rígida en el formulario:
export const myValues = [
{
code: 'option1',
name: messages.op1,
},
{
code: 'option2',
name: messages.op2,
},
];
Validación
Los campos de entrada ya no manejan la validación. Puede crear la validación de campos por separado y usar la propiedad stateMessages para mostrar los resultados de la validación. Consulte la página Validación para obtener más información al respecto.
La validación se puede realizar en el lado del cliente o en el lado del servidor. Cuando se realiza desde el lado del cliente, puede decidir si la validación ocurre mientras el usuario navega por los campos del formulario, utilizando el evento onChange de cada componente individual, o solo al final, cuando se envía el formulario. Además, debe decidir dónde se muestran los mensajes (por ejemplo, en la parte superior de la página o en el nivel de entrada). Para obtener más información, consulte Mecanismos de validación y mensajería.
Pruebas de accesibilidad al formulario
Asegúrese de que el formulario cumpla, al menos, los requisitos básicos de accesibilidad:
- Está disponible para lectores de pantalla.
- Se puede navegar por él mediante el teclado.
- Tiene el contraste adecuado.
Puede obtener más información en nuestra página sobre accesibilidad.
Redacción de pruebas para sus formularios
Para que su formulario funcione adecuadamente, asegúrese de redactar pruebas completas y bien pensadas. Puede obtener más información en nuestra sección integral sobre pruebas.