2020-03-25
|~4 min read
|780 words
A little over a year ago, I first discovered the power of Event.preventDefault
and HTMLFormElement.reset
and wrote about it Better Form Submissions with Event.preventDefault and HTMLFormElement.reset.
Despite having that post as a reference, I found myself struggling to understand why my form wasn’t behaving as I expected today.
I was playing around with an email submission. After getting the initial wiring hooked up, I decided to add client side form validation by adding a pattern to my input
tag to catch basic violations.1
Per MDN’s page on the input
element:
pattern The pattern attribute, when specified, is a regular expression that the input’s value must match in order for the value to pass constraint validation . It must be a valid JavaScript regular expression, as used by the RegExp type, and as documented in our guide on regular expressions ; the ‘u’ flag is specified when compiling the regular expression, so that the pattern is treated as a sequence of Unicode code points, instead of as ASCII. No forward slashes should be specified around the pattern text. If the pattern attribute is present but is not specified or is invalid, no regular expression is applied and this attribute is ignored completely. If the pattern attribute is valid and a non-empty value does not match the pattern, constraint validation will prevent form submission. > Tip: If using the pattern attribute, inform the user about the expected format by including explanatory text nearby. You can also include a title attribute to explain what the requirements are to match the pattern; most browsers will display this title as as a tooltip The visible explanation is required for accessibility. The tooltip is an enhancement. See Client-side validation for more information.
This seemed straight forward enough. Add a pattern. Use the title to assist in providing an explanation. No matter what I did though - my pattern didn’t seem to be validating! I tried simpler patterns. I opened up code sandboxes and they worked. What was going on?
The issue, it turned out, was where I’d placed the logic. Instead of attaching the form logic to the form’s onSubmit
handler like I had in my example a year ago, I placed it in the form button’s onClick
.
While this works for most basic use cases, the preventDefault
will disable the native validation when attached to the onClick
event, but not onSubmit
.2
TIL.
At a high level, my form looked like:
function MyForm() {
const handleClick = (event) => {
event.preventDefault()
/* ... */
}
return (
<form>
<input />
<button onClick={handleClick}>Submit</button>
</form>
)
}
Once I moved the handler to the appropriate event (onSubmit
) everything started working as desired:
function MyForm() {
const handleSubmit = (event) => {
/* ... */
}
return (
<form onSubmit={handleSubmit}>
<input />
<button>Submit</button>
</form>
)
}
I put together a CodeSandBox to help me see these differences.
Note: It’s worth noting that in the example, there’s no need to use the ref
in the handleSubmit
version (FormOne), however, in practice, this was useful because the submission was asynchronous. By having this ref, I could prevent the automatic submission of the form - which loads a new page and is why we use preventDefault
in the first place - until function had resolved. Once that happened, I would know what to display - which in my case wasn’t a new page, but a status update on the form that the form had been successfully submitted.
If you’re working with vanilla JS, you can apply custom validation too. Here’s an example I found from the W3 Spec helpful in seeing how you might attach a validator function:
<label>Feeling: <input name="f" type="text" oninput="check(this)" /></label>
<script>
function check(input) {
if (
input.value == "good" ||
input.value == "fine" ||
input.value == "tired"
) {
input.setCustomValidity('"' + input.value + '" is not a feeling.')
} else {
// input is fine -- reset the error message
input.setCustomValidity("")
}
}
</script>
While knowing about preventDefault
and the form reset
are powerful tools - it’s equally important to understand which events they are best coupled with.
Before today, I had no idea that the preventDefault
disabled the native validation functionality of the HTML5 input
components when attached to the onClick
, but not the onSubmit
events!
Hi there and thanks for reading! My name's Stephen. I live in Chicago with my wife, Kate, and dog, Finn. Want more? See about and get in touch!