Skip to content

cookbook entry on form validation #1324

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 4 commits into from
Jan 3, 2018
Merged

cookbook entry on form validation #1324

merged 4 commits into from
Jan 3, 2018

Conversation

cfjedimaster
Copy link
Contributor

Addresses issue #1314 - a cookbook version of my blog entry. I modified the text to switch from "I" to "we" and made a few other minor edits.


Form validation is natively supported by the browser, but sometimes different browsers will handle things in a manner which makes relying on it a bit tricky. Even when validation is supported perfectly, there may be times when custom validations are needed and a more manual, Vue-based solution may be more appropriate. Let's begin with a simple example.

For my first example, let's create something as simple as possible. Given a form of three fields, make two required. Let's look at the HTML first:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a bit redundant as you said, "let's begin with a simple example" above. We try to use "we" instead of "my" in teaching as well. I'd suggest beginning the second paragraph with "Given a form..."

</p>

<p>
<label for="name">Name<label>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please indent the labels and inputs within the p tags, thanks!

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FYI, after I make this (and the other edits), I'll be sure to update the codepen's too.

@sdras
Copy link
Member

sdras commented Dec 16, 2017

Thanks Raymond! I'll have some time this weekend to look it over and provide feedback.


Let's cover it from the top. The form tag has an ID that we'll be using for the Vue component. There's a submit handler that you'll see in a bit, and the action is a fake URL that would point to something real on a server someplace (where you have backup server-side validation of course).

Beneath that there isa paragraph that shows or hides itself based on an error state. This is a personal preference of mine when building forms. I like a nice simple list of errors on top of the form. You may like error handling by the fields themselves. Use what works. Also note I'm going to fire my validation on submit rather than as every field is modified. Again, this is a personal preference.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Separate "isa" to "is a". Please remove the references to personal preferences, this is a cookbook, so this is implied. Please switch the "I" statements to "we".

})
```

As you can see, we've added `validEmail` as a new method and it is simply called from `checkForm`. Nothing too crazy, but a good example I think. You can play with this example here:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You don't need the "nothing too crazy" sentence here


## Another Example of Custom Validation

For the third example, we've built something you've probably seen in survey apps. The user is asked to spend a "budget" for a set of features for a new Star Destroyer model. The total must equal 100. First, the HTML.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is well stated, thanks

</form>
```

Note the set of inputs covering the five different features. Note the addition of .number to the v-model attibute. This tells Vue to cast the value to a number when you use it. However, there is a bug with this feature such that when the value is blank, it turns back into a string. You'll see the workaround below. To make it a bit easier for the user, we also added a current total right below so they can see, in real time, what their total is. Now let's look at the JavaScript.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I appreciate the attention to detail in this example. Really nice.


## Server-side Validation

In my final example, we built something that makes use of Ajax to validate at the server. The form will ask you to name a new product and will then check to ensure that the name is unique. We wrote a quick OpenWhisk serverless action to do the validation. While it isn't terribly important, here is the logic:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a link to OpenWhisk in case people aren't familiar with it

<p data-height="265" data-theme-id="0" data-slug-hash="BmgzeM" data-default-tab="js,result" data-user="cfjedimaster" data-embed-version="2" data-pen-title="form validation 4" class="codepen">See the Pen <a href="https://codepen.io/cfjedimaster/pen/BmgzeM/">form validation 4</a> by Raymond Camden (<a href="https://codepen.io/cfjedimaster">@cfjedimaster</a>) on <a href="https://codepen.io">CodePen</a>.</p>
<script async src="https://production-assets.codepen.io/assets/embed/ei.js"></script>

## Vue Form Validation Libraries
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd appreciate a little more consideration here. Thanks for including it at our request, but we'd call this section "Alternative Patterns" and I'd love it if it addressed why you might use a library in place of what you've written above and what the tradeoffs are (one is larger, but it might cover more use cases for different types of forms if you know you're building out more forms later. They will probably stay up to date with browser support based on community improvements etc)

Thanks!

@cfjedimaster
Copy link
Contributor Author

Thank you for all this! I've got a busy weekend so I may not get the fixes till Monday.

@cfjedimaster
Copy link
Contributor Author

Edits have been applied. Updating the Codepen's now. Thank you again for the review!

@sdras
Copy link
Member

sdras commented Dec 19, 2017

Great! Give me a day or so and I'll take a look. Thanks!

}
}
})
```
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This seems like it needs to be kept from going below 0. The negative numbers don't make much sense if the user clicks down instead of up

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One could see it as a strong vote against. :)

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This goes for the first example with the age (or maybe built into the second one) as well. Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cfjedimaster good point! Maybe we leave this example as is but change the first one with the age. Pretty sure you can't be negative years old :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've added min="0" to the article (not yet in code), please add to the CodePen. Here is the complete line for reference:

<input type="number" name="age" id="age" v-model="age" min="0">

})
```

Fairly short and simple. We default an array to hold errors and set null values for the three form fields. The checkForm logic (which is run on submit remember) checks for name and age only as movie is optional. If they are empty we check each and set a specific error for each. And that's really it. You can run the demo below. Don't forget that on a successful submission it's going to POST to a non-existent URL.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The weird part about this demo is that it posts to nothing, so playing with the demo will give the user a blank page. You kind of address this in the last sentence, but I would either add a success to the demo, or make the last sentence a warning, and say specifically that the POST URL will go to success page that they will have to build. (nitpicky, I know, but right now the demo feels a little funny.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a bit unsure how to handle this. I worry that if I post to a real URL, like Vue's home page, that would be confusing as well. Could I make the last sentence stronger? Like maybe just bold it? And perhaps add an exclamation mark? And then maybe we can see if reader's get confused by itself and send us feedback?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will only update within the iframe of the embed, so that would be ok. Can you please try it out and if that doesn't work we can go back and do bold or something.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we want to change the embeds and text? If both, I'll update, if just the embeds, you can do that on your end, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Disregard previous comment.

}
})
```

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this.name here should be in backticks for code :)

</ul>
</p>

<p>
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I quite like this example, but I think the text here could make it clearer that you have to select exactly 100. Maybe something like "Given a budget of 100 dollars, indicate how much you would spend on the following features for the next generation Star Destroyer by making the Current Total of features add up to 100:"

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I went with: " Your total must sum up to 100.".

@sdras
Copy link
Member

sdras commented Dec 28, 2017

Sorry for the delay, my relatives were here for the holidays. This is looking really great! I started moving the examples over to CodePen. Once these things are fixed, I think it will be ready to get in :) Great work. I think it will be really helpful.

@cfjedimaster
Copy link
Contributor Author

Thanks again for this - my rough ETA is Tuesday. Note - for cases where the codepen needs to be updated, I'll be sure to leave a note here so you can edit the official Vue copy.

@sdras
Copy link
Member

sdras commented Dec 29, 2017

Awesome, thank you so much Raymond!

@cfjedimaster
Copy link
Contributor Author

All changes pushed. Only open question is the warning about form submissions.

@sdras
Copy link
Member

sdras commented Jan 2, 2018

Looking great! Answered the form submission query inline above, that's the last piece and then I'll merge :)

@cfjedimaster
Copy link
Contributor Author

Ok, last thing changed.

@sdras
Copy link
Member

sdras commented Jan 3, 2018

Congrats! Looks awesome!!! 🎉 Thanks for your contribution! I'll be following up with codepen embeds from vue's account later tonight.

@sdras sdras merged commit 12d5785 into vuejs:master Jan 3, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants