Conf42 JavaScript 2021 - Online

Vue.js form validation with vee-validate v4

Video size:

Abstract

The Talk will showcase the different ways frontend developers do form validations and how vee-validate v4 makes it much easier to accommodate for these needs and use-cases.

We will cover:

  • JS form validation
  • “Classic” HTML form validation with backend framework
  • “Modern” AJAX form validation
  • Multistep forms
  • JSON schema generated forms
  • Composing the validation logic into custom components with Vue.js composition API

Summary

  • Abdelrahman Awad is a frontend engineer at Octopods. He created and maintained Vvalidate for vjs since 2016. He writes about JavaScript typescript vuejs on his blog. Today he will talk about Vuejs form validation with veevalidate V four.
  • There are various pain points when it comes to forms manifesting as friction in a lot of areas. Most libraries try to address these issues for the developer. Value tracking is really complicated because it depends on how you express and declare your forms. There is also the UI and UX aspect, and forms are tedious.
  • veevalidate V tries to solve these pain points. Also, it tries to offer a progressive API to match the Vuejs ideology. caters to those who are using it as an enhancement layer for their application. Everything for these developers scales well to match their needs.
  • A typical forum usually has three sections: state binding, state declaration and value retrieval. vvaldi tries to reduce it or completely eliminate it by reducing it to a single section. You only have to declare your fields and give it a name. That name can act as a field path in the model tree.
  • Having a Javascript functions as the baseline really makes sense and it's a must have. It opens the door for using third party libraries, form validations,js and custom functions. Using validation schemas you can pretty much build whatever dynamic schemas that you want to validate your forms.
  • UI nux is a form generator that allows you to add progressive integration. For example, you can prevent submission if the form is invalid and submit using exactly the same flow if everything is valid. There are a lot of meta flags like touched dirty and validated, and many others. Check the documentation for more information about what else is available here.
  • You can use the components API along with the composition API. The composition API allows you to integrate the vvalidate features into your own components. This is the main goal of the composition by veevalidate help you build your own custom components and custom forms.

Transcript

This transcript was autogenerated. To make changes, submit a PR.
You. Hello. Thank you for being here today. These I will talk about Vuejs form validation with veevalidate V four, so let's get to it. First, a little bit about me I am Abdelrahman Awad frontend engineer at Octopods. I created and maintained Vvalidate for vjs since 2016. I write about JavaScript typescript vuejs on my blog, locerit.com, so check it out if you are interested in that type of content. Also, you can give me a follow at logarithm on Twitter. So forms are hard, but what makes these so there are various pain points when it comes to forms manifesting as friction in a lot of areas, and I have identified the most painful areas to be these ones, or at least the most common ones that we run into. And this is also as seen in other libraries. So most libraries try to address these issues for the developer. So let's start with value tracking. So value tracking is really complicated because it depends on how you express and declare your forms. If you are using native HTML elements and you don't really have Javascript going on here, then value tracking is done automatically for you because that's native HTML behavior when it submits the form to some back end server using full page reloads. But if you have Javascript forms then it becomes a lot more involved because you need to have two way bindings between your inputs and your data models in memory and keep them synced. This can be tricky and there is a lot of caveats here. For example, the field types like checkboxes, radio buttons and file inputs, so each really file type really has its own quirks that you need to makes into account when tracking your form values. The other pinpoint is validation error messages. So with validation it can be really simple or it can be really complicated again based on your needs. For example, you can have synchronous validation, or you can have a pipeline of asynchronous validations building on top of each other, so managing this can be really difficult. Also the way and the style of you expressing your validation intent. Is it global validations that you call upon using some kind of friendly string formats like Laravel or other frameworks? Or is it explicit functions, explicit Javascript functions that you import and pass around explicitly to make everything clear? So it really depends on your use case. Also error messages it can be really hard to normalize the generation of error messages because error messages are complicated and it begins how you phrase them. So if you include the field name in the error message like this field or these email field is required, or this name field is required. You have an issue here because you have to include the field name in the generated message. But if you avoid that and use simpler messages like this field is required, this field must be a valid email. Then you escape this. But there is localization, and not all of languages agree that you can be neutral about fields. So it is really complicated. There is also the UI and UX aspect, and forms are tedious. Users hate filling out forms, and you as a form filler, really you hate this, and as a developer, you probably hate them as well. So the issue with forms here is if they are repetitive and you might be asking a lot for information here. So if the experience is really poor or really frustrating, the user won't bother and you will be testing their patience. So depending on how much fun the interaction with your form is, the user may choose to fill out the form or lose patience and maybe decide it's not worth it to go through this. And this defeats the whole purpose of having a form, right? You only have it to collect some values. And yeah, there is also organization. So let's say you are building a really complex admin dashboard application, and this admin dashboard application has a lot of cruds and a lot of crud forms and crud pages. And these forms usually exist in two modes, create and edit. So in that case, how are you going to organize all these validation rules, all of these fields, all of these forms and messages? That's a lot of stuff to organize. So the validation library should give you at least some kind of units of organization that allow you to do something like that. There is also the debugging and developer experience. Most validation libraries don't really have any debugging tools, and this can be really frustrating and can send you in a wild goose chase when you have this form that isn't submitting and you can't really figure out why it's not submitting. So having the binding tools is really beneficial here. So veevalidate tries to address some of these issues, but let's talk more about it first. Vvalidate is currently these most popular VueJs forms validation library at around 1.4 million downloads per month and 8.6k stars on GitHub. So with that out of the way, let's talk about the goals. The goal of veevalidate V to solve these pain points and using the word solve can be a lot of claim here. So at least it will reduce the friction that you encounter with these pain points, but it does a really good job at reducing that friction, and we'll see a lot of examples on each of these points. Also, it tries to offer a progressive API to match the Vuejs ideology. So Vuejs has this ideology or mantra of it being the progressive JavaScript framework, and it really does a good job of doing so. So what does it mean? It means vuejs caters to those who are using it as an enhancement layer for their application. So for those who just want to sprinkle some Javascript into their application to make some widgets interactive and some aspects of their page interactive without having to do everything in JavaScript, Vuejs really offers a really good job for that use case because you can import it from the CDN and integrate it right into your application with really minimum effort and really minimum setup. You don't really have to set up webpack or a really complicated front end stuff to get it working. On the other hand, you have these who want to build a fully working single page application that uses Vuejs for routing, state management and rendering. So everything for these developers scales well to match their needs. So yeah, veevalidate v tries to follow that guideline to be really easy to integrate with minimum effort, almost like a search and replace manner, but also catering for those who want to do more and want to do a lot of and get a lot of benefit out of the tool that they are using. There is also the composition first design approach. The composition API is similar to the react hooks API, which allows you as a developer to integrate third party logic into your own components. Also first party logic of course, but it allows you to integrate some kind of logic into your own components in a really reusable manner. So vvalid doubles down on that and you will see in a few minutes how it does. So first let's talk about the building blocks. So this is the most basic form you have. You have a form element and an input element. So let's say we want to convert this form to a veevalidate v form. All you have to do is remove the form element and use the form components. Notice the difference is the uppercase forms component. The first letter is uppercase and the input element was removed and we added the field component instead. And that's it. So it's almost assertion replace API. But of course there are a lot more to it than that. But this is the basic way to get veevalidate into your project and having the same exact render output as the previous native forum. So let's talk about the first pain point. Value tracking this typical forum usually have this three sections inside it has state binding, state declaration and value retrieval. So the state binding section contains the markup for your elements and it is two way binded to your state declaration or one way binded depending on your needs. There is also the value retrieval section where you retrieve the values that you have declared so you can send them to the server. The problem with this is there is some friction here, and it can be too much friction if you have really large forms. Let's say you want to add a field. If you added this field, you may forget to bind it to your state, or you may forget to retrieve it before sending it to the API. And that means the form may be missing some data or maybe not working as you have expected. And this is a friction I'm talking about here. So vvaldi tries to reduce it or completely eliminate it by reducing it to a single section. So you only have to declare your fields and give it a name. That name can act as a field path in the model tree. So for example here we replaced all the inputs with the field component and veevalidate v automatically create the models for them and bind the elements, the input elements to these models. Another thing is another added benefits is you can use JavaScript object syntax or array syntax to express nested fields. So we have the links fields here, we have links of these zero and links of one. And when vvalid sees it, it understands that you want to create a field, a field element that is tracked in the first element of an array called links, and you want to create another field that is tracked in the second element of the array called links of links. So it creates that these for you. It reverses the names into default into a form tree generates for you, and retrieves it for you automatically when you try to submit that form. And really that reduces a lot of effort here. So if you need to add a field, you just throw it in in the forms and you are done. So let's talk about the most important aspect, and it's in the name of the library validation. So we developers come from different backgrounds. Me myself, I was a backend engineer, library backend engineer, then a node JS backend engineer, then switched over to front end. So with this I have a lot of experience of how each ecosystem expresses their validations, and that really gives me ideas on how and the best way for each use case. For example, you always need to have a baseline. So having a Javascript functions as the baseline really makes sense and it's a must have. So having JavaScript functions act as form validations opens the door for using third party libraries, form validations, js and custom functions. So it's really important to have it also integrations with other frameworks or inspiration from other frameworks. For example, there is the back end inspired string expression that inspired with larvae validation syntax. Larvae validation syntax is very easy, very compact and easily maintainable, and because of their global nature, so they need to be defined globally. That makes them really useful in applications when you have a lot of forums, so admin dashboards for example, and in these forums you really need to call upon validations rules without having to worry about declaring them each time you need to use them. So this really makes sense here. There is also the schema validators that you can use to build really complex and really dynamic validation schemas using yup and Zod and many others. You can use them to make, for example, a field is required when another field in the forms is bigger than five. So you really can really make these arbitrary conditions and you can pretty much build whatever dynamic schemas that you want to validate your forms. So let's see what each one looks like. With Javascript functions it's really straightforward. You create a function, that function receives a value. Then you can either return a boolean like true, and if you return true, that means that the field is valid. Otherwise you can return a string and that says this is the error message for that field. This field is invalid and this is the error message. It's really straightforward and all you have to do is pass it to the rules property of the field component field validation with larvae rules is similar, but it uses strings. So you grab the companion library called add v validity rules, and you basically grab the rules that you will need and you define them in your application. Note that you only have to do this once, so you don't really need to do this in each component. You can do it at the entry point of your application and not worry about it again. And once you define them, you can call upon them using string. So in the rules property you can pass a string that's expressed as required pipe email. So this is a required email field. You can use these up schemas to validate your fields. So in this example right here, we grab the string schema from yep, and use it to build up a required email schema. And we pass that schema to the field, same property rules and veevalidate v first class support for it and will understand that you want to do schema validation using this schema. Another thing that's really exciting here is you can use these schemas, specifically object schemas, to specify a validation schema for the entire forum. So you no longer have to specify a validation rule for each field. And this really makes it much more easier to reason about the validation rules of that forum. So you don't have to go back and forth between the script and the template a lot. And this reduces this friction as well. So there is some friction here, but you can completely eliminate it by using validation schemas. Then you define your schema object. For example these we have an object schema that contains an email that is a required email, a name field that is a required string, and another string called password that is required and must be minimum six characters long. And this will allow veevalidate v use these schema for your fields. It will validate each field according to the schema and it will automatically assign the error messages properly according to that schema. So this makes it really easy to maintain such forms and makes it really pleasant to use them. So let's talk about the progressive integration aspect. Right here we have this basic form, really basic form that uses the full page reload to submit the data, which is the native way to submit your forms. So this form submits via a post method these four fields to the action endpoint register. And typically you have this in your back end application, or in your back end rendered application can be laravel, can be rails, or it can be plain old php or plain old whatever. So this forum typically behaves like this. You submit the forum and it performs a full page reload. The server validates and redirects you back to the form if there are any errors. Otherwise it will move on to the next page, log you in or whatever. But let's say you want to add some sprinkle some Javascript here to spice it up a little bit. For example, you want to prevent submission if the form is invalid and submit using exactly the same flow if everything is valid. So you can do that using search and replace. It can be as easily as this. So you remove the form elements and use the form components. You remove the input elements and use the field components. And we also add the error message component that we use to display errors. Each error message component can have a name which is the same name of the field that it will display the error message for. So it needs to match the field names. Also we need to provide the validation schema and in any of the ways that we saw before, or you can provide for each field its own rules, it doesn't really matter. But validation schemas, I really recommend using them whenever you can. But right here we do. So what veevalidate will do here is it will automatically identify that you don't have a validation submission function, so you don't really want to hijack the form submit event, right? And what it will do is when the user submits a form, it will validate the forms and it will render any error messages and then it will branch off. If the form is valid, it will perform a full page reload and submit the form normally, just as if you had no Javascript at all, similar to the same behavior we had before. Nothing extra here. But if the form turns out to be invalid, then it will prevent the submission and display these error messages. So it did really what you want and it kind of understood your intention here. If you have a submit handler here, it will then act as it will only execute that handler when the form is valid, and it will prevent submission in either case because it then assumes yes, you really want to hijack the submission here. So we will do that. So let's talk about UI nux, and we will cover through a couple of examples really quickly. Right here we have form interaction flags. You can do a lot more than this example, but this is just a taste of what veevalidate really has to offer. So let's say you want to disable the submit button until the form is valid. You can do this by accessing the valid meta flag, or you can display the submission progress by checking the submitting flag. And this flag is true whenever the form is being validated and submitted, and will turn to false once it's done. So you can really use it to spill some spinners or change some text, or disable your inputs if you really want to. So it's really nice to use, you can do a lot more. There are a lot of meta flags like touched dirty and validated, and many others. So yeah, you can really build whatever experience and craft whatever experience you really want. Check the documentation for more information about what else is available here. Another example here is handling invalid submissions. This is a fairly new addition to the library, so a lot of users really wanted to do something extra when the user submits the form and turns out invalid, which is really useful if you have this long form and you really want to scroll the user to the input that they cannot see so the user may be trying to submit the form, but they don't understand exactly what's going on. So it can be really useful to just scroll them. Yeah, here is these field that has an issues please fix it so we can really do that. Using this simple example we grab the first error key and that can happen to be the field name and then you can build your form for that to be correct and then query that input, grab it and scroll it into view and you are done. So three liners really improve the experience of really wrong forms or multistep forms if you have them. So yeah, you can do a lot more with veevalidate v terms of your IU nux, but this is just a couple of examples. So form generators form generators are really complicated, but using vvalidate you can really get away with a very basic form generator. Vvalidate itself doesn't offer any form generator for you out of the box, but you have all the tools to build your own. But if you don't really know what is a form generator, it is basically a component or a function or something that accepts a JSON object or a JavaScript object and generates your fields and forms based on that object. They can be dynamic and it makes it really easy to retrieve your forms from the API, for example, and they are really useful and really reduce, they can really boost your productivity when working with a lot of forms. So right here in this tutorial, it's only eight lines long if you leave out the schema fields definition and yeah, this is the most basic form generator. Of course you can expand upon it more to include more complicated inputs like selects custom components and more. And there is actually a tutorial in the documentation covering that you can also use specialized libraries that have first part support with vvalidate. Again, because of the composition API that we will come to just a minute. Vvalidate can be integrated with other libraries and one such library is forms view late and form view late really takes it to the next level with form generated. It's completely UI agnostic, so it doesn't really care what you want to render. You can render custom components or you can render a native HTML element with formvalate. You can then render your inputs, integrate them with vvalidate without really a lot of work. So you only have to declare your fields and if you really need this kind of functionality. So form generation and validation to your application, this can be really useful and it will take care of the hard and heavy lifting for you. So you only have to care about the actual application logic because most of the things are done for you. Speaking of the composition API. So the composition API again allows you to integrate the vvalidate features into your own components. And you can think of vvalidate as this central API that has two outlets, the composition API outlet and the components API outlet. You have seen the components API so far and the components API is actually the same. They both offer the same feature sets and actually the components API is built using the composition API. This means that you can mix and match between them. They are not mutually exclusive. You can use the components API along with the composition API. So if you want to build custom field components with validation, value tracking, and all of the features I showcased, you can use a function called use field for forms components, you can use a function called use form. This is an example for such a basic input component called input text. And this components all it does, it just imports use field from veevalidate, calls it and basses the field name to it, which will be appropriate most likely. And it grabs two things, the value and the error message. The value is the internal model that veevalidate creates for you, so you can actually bind it to your actual input and it will automatically be validated whenever that value changes. Veevalidate will populate the error message with any information or the proper error message. Forms, custom forms, it is similar. You grab the use form function, you can pass the validation schema to it and other configuration properties. You can grab a handle submit function from it and there are a lot of stuff you can grab from it. But for this example we are only grabbing the handle submit which creates submission handlers for you. These submission handlers you can bind to your listeners, so you can listen for a form submit event and trigger the submit function for it. You can use it on bottom clicks, you can really use it in any kind of events, and you can even call it manually in your javascript and they all behave the same. They will validate the form and these executor callback if everything is valid. Otherwise they will just validate the form and won't do anything extra. Let's check an example from before and after. So before we used the components API, which was a little bit verbose because we had to use the field component and the error message components and we have a bunch of fields. So this became repetitive really quickly. But if we use a composition API to build our own input text component, we can then really express our forms in terms of one liners. So one liner name, one liner email and one liner password and that's it, we are done. We get value tracking error messages for those elements and we get the rendering as well. And this is really the main benefit of using the composition API. You should use it to build your own components and not veevalidate v JavaScript values. If you really want to just validate JavaScript values then you are better off using other libraries. This is the main goal of the composition by veevalidate help you build your own custom components and custom forms. In this example, notice that we use the form components with our custom input text component. Again, this is because it's all built on the composition API, meaning you can mix them and they will work seamlessly together. You can do the opposite as well. So let's check this last thing, which is the Vuejs diff tools plugin right here. We have this really nice forum and we have the view diff tools. Normally you have the view diff tools. View diff tools offers inspectors that allow you to view the components these in different ways. So the default one is called components. But once you use any kind of vvalidate stuff, either the composition API or the components, you will see a new inspector called veevalidate v. You click on it, you will notice that it renders a completely different view. It shows you the nodes in terms of not components but in terms of fields and forms. So right here, this is a form node, this is a name node and I'm calling them nodes because each component can contain multiple fields or multiple forms. So it's not really accurate to call each one components. So they are just nodes. So each node can have a summary of their state like you can see down here. And yeah, form of course have more states, so of course they have more stuff to show. But yeah, you get access to initial values, current values, errors and any other meta information. At a glance you get these tags called form field that tells you which node is which. So this is a form node, this is field node and so on. They are in red. So notice once I start filling out these element they turn to green. This is really neat because vvalid now tells you what each component validity is just at a glance without you having to really dig deep and see why is these field is not valid, right? So yeah, just simple color change can tell you a lot. So here right now we can tell that this form isn't valid because it's red and it isn't valid because this field is the only one that's invalid, so makes complete sense. And if we try to submit it, this does this little shaking, which is a small validations that we have here, but we show an error message here. If we click on the confirm password node, notice that we have the error here and the valid flag is turned to false. And if we go to the form in the errors object, we have passwords do not match for the confirmed password field. So let's try filling it out. And these errors are empty. The hover form is valid, it is green. Same thing for the confirmed buster field. If we try to submit it, everything submits and it works nicely. You can have do a lot of other actions to debug your state. For example, you can clear the forms so you can clear individual inputs. So let's click on the buzzer field. You can clear it by clicking on this icon and yeah, it is cleared and you can force validate it. You can click on the form node and clear it and also forms validations and forms validation it. So this is really nice and allows you at a glance to figure out what's wrong. So if you have this form that isn't submitting, you can check the errors and figure out why it's not submitting. Maybe it has some field that you forgot to show, or maybe you forgot a rule. So yeah, that's all for this talk. So there is of course a lot more that we didn't cover because there is a lot of API and components that makes it really useful for you. For example array fields, multifaceted step forms, localization libraries, integrations, which is libraries like quasar, beautify, toolwind, the headless UI and more. Check out the documentation, there is a lot of information each of them and leave your feedback. So thank you for attending this talk and see you around.
...

Abdelrahman Awad

Senior Frontend Engineer @ Octopods

Abdelrahman Awad's LinkedIn account Abdelrahman Awad's twitter account



Awesome tech events for

Priority access to all content

Video hallway track

Community chat

Exclusive promotions and giveaways