This course is archived!

While the concepts of this course are still largely applicable, it's built using an older version of Symfony (4) and React (16).

Buy Access to Course
23.

Form Validation State

Share this awesome video!

|

Keep on Learning!

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

When the user tries to submit a negative quantity, we need to show an error! On a React level, this means that we'll need new state to store that message. And, like we just discussed, because this state is really tied to our form and is meant to power the UI, the best place for it is inside RepLogCreator.

To add state, we always start the same way: initialize it in the constructor: this.state = an object, and call it quantityInputError set to empty quotes.

99 lines | assets/js/RepLog/RepLogCreator.js
// ... lines 1 - 4
constructor(props) {
// ... lines 6 - 7
this.state = {
quantityInputError: ''
};
// ... lines 11 - 22
}
// ... lines 24 - 99

Below, remove the todo and add this.setState() with quantityInputError set to Please enter a value greater than zero.

100 lines | assets/js/RepLog/RepLogCreator.js
// ... lines 1 - 24
handleFormSubmit(event) {
// ... lines 26 - 31
if (quantityInput.value <= 0) {
this.setState({
quantityInputError: 'Please enter a value greater than 0'
});
// ... lines 36 - 38
}
// ... lines 40 - 50
}
// ... lines 52 - 100

And when the form submit is successful, we need to make sure any existing error is removed. Copy the setState() line and set it to an empty string.

100 lines | assets/js/RepLog/RepLogCreator.js
// ... lines 1 - 24
handleFormSubmit(event) {
// ... lines 26 - 47
this.setState({
quantityInputError: ''
});
}
// ... lines 52 - 100

State, check! Down in render, as always, start by destructuring the variable: const { quantityInputError } = this.state. Let's use this to do two things: add a class to make the form element look red and print the message.

100 lines | assets/js/RepLog/RepLogCreator.js
// ... lines 1 - 52
render() {
const { quantityInputError } = this.state;
// ... lines 55 - 93
}
// ... lines 95 - 100

Because we're using Bootstrap, to make the field red, the form-group div needs a new has-error class. Empty out className, enter into JavaScript mode and use "ticks" to use a "template literal". This makes using multiple classes with logic a bit easier: re-add form-group, then type ${} to do "string interpolation". Oooo. Inside, if quantityInputError then print has-error, else print nothing.

100 lines | assets/js/RepLog/RepLogCreator.js
// ... lines 1 - 55
return (
// ... lines 57 - 75
<div className={`form-group ${quantityInputError ? 'has-error' : ''}`}>
// ... lines 77 - 86
</div>
// ... lines 88 - 92
);
// ... lines 94 - 100

The Cool Conditional String Printing Syntax

And to actually print the message, go down after the input. Here, I don't just want to print the error, I want to surround it in a red div, but only if there actually is an error. We could use the ternary syntax here... and use some inline JSX. That's fine.

But instead, I want to show you a cool, but weird, shortcut syntax that we can use whenever we want to print a string only when that string is not empty. Here it is: quantityInputError && and then the JSX: <span className="help-block">, print quantityInputError, close the tag, and exit from JavaScript mode.

100 lines | assets/js/RepLog/RepLogCreator.js
// ... lines 1 - 75
<div className={`form-group ${quantityInputError ? 'has-error' : ''}`}>
// ... lines 77 - 85
{quantityInputError && <span className="help-block">{quantityInputError}</span>}
</div>
// ... lines 88 - 100

Woh. Before we talk about this, try it! Move over, make sure the page is fully refreshed, select an item, be annoying and use a negative number and... there it is! Oh, it's ugly: we'll fix that soon.

But first, about this syntax! It's weird because this bit of code works different in JavaScript versus PHP! In JavaScript, if quantityInputError is empty, or "falsey", this return false and we print nothing. But if quantityInputError has some text in it, so, it's "truthy", then JavaScript returns the second part of the expression: our JSX. So, this entire block will either return false or this JSX. In PHP, this would always return false or true.

So... yes, this is another fancy syntax. If you love it, nice! If you hate it, use the ternary syntax instead.

Cleaning up the Form Design

Before we move on, oof, we need to make this look less ugly. Go back into RepLogs and scroll down. Add a few divs: className="row" and another className="col-md-6". Move RepLogCreator inside.

77 lines | assets/js/RepLog/RepLogs.js
// ... lines 1 - 30
return (
// ... lines 32 - 58
<div className="row">
<div className="col-md-6">
// ... lines 61 - 63
</div>
</div>
// ... line 66
);
// ... lines 68 - 77

Then, back in RepLogCreator, find the form element and... remove the form-inline class.

100 lines | assets/js/RepLog/RepLogCreator.js
// ... lines 1 - 55
return (
<form onSubmit={this.handleFormSubmit}>
// ... lines 58 - 92
);
// ... lines 94 - 100

Give your browser a nice refresh. This puts the form elements onto their own lines. And that makes our validation error look much nicer.

We'll handle server-side validation later. But right now, let's talk about a totally different way of handling form data: controlled components.