We have the following contact form in React using https://react-bootstrap.github.io/forms/overview/
let contactForm =
(<Form ref={formRef} onSubmit={sendEmail} className='toggle-contact-form'>
<div className='toggle-contact-form__header'>
<p className='p1'>Please Reach out!</p>
<p className='p2'>Use our contact form to reach out with any questions, concerns or issues with the website.</p>
</div>
<Form.Row style={{ paddingTop: 20 }}>
<Form.Group as={Col} controlId='name'>
<Form.Label>Name</Form.Label>
<Form.Control className='cbb-home-input' placeholder='required' />
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col} controlId='email'>
<Form.Label>Email Address</Form.Label>
<Form.Control className='cbb-home-input' type='email' placeholder='required' />
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col} controlId='phone'>
<Form.Label>Phone Number</Form.Label>
<Form.Control className='cbb-home-input' placeholder='optional' />
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col} controlId='message'>
<Form.Label>Message</Form.Label>
<Form.Control className='cbb-home-input' as='textarea' rows='2' placeholder='required' />
</Form.Group>
</Form.Row>
<Form.Row>
<Form.Group as={Col} controlId='button'>
<Button variant='primary' type='submit' disabled={true}>
{isSubmitting ? 'Sending Email...' : 'Submit'}
</Button>
</Form.Group>
</Form.Row>
</Form>);
Currently the button disabled={true}
, we'd like to make this conditional on the Form.Control
elements for name
, message
both being not empty, and email
being a valid email address. Currently we have no form validation. Is it possible to validate this form as such?
The Bootstrap docs suggest using a library to make this process easier:
It's often beneficial (especially in React) to handle form validation via a library like Formik, or react-formal. In those cases, isValid and isInvalid props can be added to form controls to manually apply validation styles.
Since we need access to the values of the input fields, we'll need to use controlled components to hold the form data. First we will set up some useState
variables to hold the data:
const [name, setName] = useState("");
const [message, setMessage] = useState("");
const [email, setEmail] = useState("");
Then we need to use those state variables to handle the data in form fields by setting the value
and onChange
props:
...
<Form.Control
value={name}
onChange={(e) => {
setName(e.target.value);
}}
className="cbb-home-input"
placeholder="required"
/>
...
<Form.Control
value={email}
onChange={(e) => {
setEmail(e.target.value);
}}
className="cbb-home-input"
type="email"
placeholder="required"
/>
...
<Form.Control
value={message}
onChange={(e) => {
setMessage(e.target.value);
}}
className="cbb-home-input"
as="textarea"
rows="2"
placeholder="required"
/>
...
Now that we have access to the form field data, we can create a variable to keep track of whether the user input is valid:
const isValid = checkValidity(name, message, email);
The checkValidity
function can check if name
, message
, and email
meet the requirements we want them too:
const checkEmail = (email) => {
return /^\w+@[a-zA-Z_]+?\.[a-zA-Z]{2,3}$/.test(email);
};
const checkValidity = (name, message, email) => {
return !!name && !!message && checkEmail(email);
};
At this point, the isValid
variable will always be updated with whether or not the current user input in the form is valid. Specifically, we are making sure name
and message
are not empty, and that email
passes a simple regex validity check.
Finally, we disable the submit button whenever isValid
is false using the disabled
prop:
<Button variant="primary" type="submit" disabled={!isValid}>
{isSubmitting ? "Sending Email..." : "Submit"}
</Button>