Lab 16: Form Validation
Objectives
- Add Form Validation
Steps
Add Form Validation
Open the file
src\project\ProjectForm.js
Initialize an
errors
object as a state variable to{name: '', description: '', budget: ''}
so we can hold form errors in the component'sstate
.src\projects\ProjectForm.js
...function ProjectForm({project: initialProject,onSave,onCancel,}) {const [project, setProject] = useState(initialProject);+ const [errors, setErrors] = useState({+ name: '',+ description: '',+ budget: '',+ });...}...export default ProjectForm;Implement a
validate
function in theProjectForm
component that meets these requirements.- Name is required.
- Name needs to be at least 3 characters long.
- Description is required.
- Budget must be greater than \$0.
Also, implement an
isValid
function in theProjectForm
component that checks whether there are any validation errors.src\projects\ProjectForm.js
...function ProjectForm({project: initialProject,onSave,onCancel,}) {const [project, setProject] = useState(initialProject);const [errors, setErrors] = useState({name: '',description: '',budget: '',});const handleChange = (event) => {...};+ function validate(project) {+ let errors = { name: '', description: '', budget: '' };+ if (project.name.length === 0) {+ errors.name = 'Name is required';+ }+ if (project.name.length > 0 && project.name.length < 3) {+ errors.name = 'Name needs to be at least 3 characters.';+ }+ if (project.description.length === 0) {+ errors.description = 'Description is required.';+ }+ if (project.budget === 0) {+ errors.budget = 'Budget must be more than $0.';+ }+ return errors;+ }+ function isValid() {+ return (+ errors.name.length === 0 &&+ errors.description.length === 0 &&+ errors.budget.length === 0+ );+ }return (...);}...export default ProjectForm;Call the
validate
function insidehandleChange
to determine if there are any errors and then set them into theerrors
state variable....function ProjectForm({project: initialProject,onSave,onCancel,}) {...const handleChange = (event) => {const { type, name, value, checked } = event.target;// if input type is checkbox use checked// otherwise it's type is text, number etc. so use valuelet updatedValue = type === 'checkbox' ? checked : value;//if input type is number convert the updatedValue string to a numberif (type === 'number') {updatedValue = Number(updatedValue);}const change = {[name]: updatedValue,};let updatedProject;// need to do functional update b/c// the new project state is based on the previous project state// so we can keep the project properties that aren't being edited like project.id// the spread operator (...) is used to// spread the previous project properties and the new changesetProject((p) => {updatedProject = new Project({ ...p, ...change });return updatedProject;});+ setErrors(() => validate(updatedProject));};return (...);}...export default ProjectForm;Call the
isValid
function on form submit and return back out of the function before saving changes if the form is invalid.src\projects\ProjectForm.js
...function ProjectForm({project: initialProject,onSave,onCancel,}) {...const handleSubmit = (event) => {event.preventDefault();+ if (!isValid()) return;onSave(project);};...return (...);}...export default ProjectForm;In the JSX returned by the component: display the validation messages using the following
HTML
template.<div class="card error"><p>error message</p></div>src\projects\ProjectForm.js
...function ProjectForm({project: initialProject,onSave,onCancel,}) {const [project, setProject] = useState(initialProject);const [errors, setErrors] = useState({name: '',description: '',budget: '',});...return (<form className="input-group vertical" onSubmit={handleSubmit}><label htmlFor="name">Project Name</label><inputtype="text"name="name"placeholder="enter name"value={project.name}onChange={handleChange}/>+ {errors.name.length > 0 && (+ <div className="card error">+ <p>{errors.name}</p>+ </div>+ )}<label htmlFor="description">Project Description</label><textareaname="description"placeholder="enter description"value={project.description}onChange={handleChange}/>+ {errors.description.length > 0 && (+ <div className="card error">+ <p>{errors.description}</p>+ </div>+ )}<label htmlFor="budget">Project Budget</label><inputtype="number"name="budget"placeholder="enter budget"value={project.budget}onChange={handleChange}/>+ {errors.budget.length > 0 && (+ <div className="card error">+ <p>{errors.budget}</p>+ </div>+ )}<label htmlFor="isActive">Active?</label><inputtype="checkbox"name="isActive"checked={project.isActive}onChange={handleChange}/><div className="input-group"><button className="primary bordered medium">Save</button><span /><button type="button" className="bordered medium" onClick={onCancel}>cancel</button></div></form>);}...export default ProjectForm;Verify the application is working by following these steps.
- Click the edit button on any project.
- Delete the contents of the project name textbox.
- Verify the error message displays.
- Test the other validation rules.