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.