Learn how to validate username uniqueness in Firebase with Angular Reactive Forms. We build a custom validator that checks the the Firestore DB for existing user records. https://angularfirebase.com/lessons/async-form-validation-in-firebase-enforce-uniqueness/

- Reactive Forms - https://angular.io/guide/reactive-forms
- Firestore - https://stackoverflow.com/questions/46549766/whats-the-difference-between-cloud-firestore-and-the-firebase-realtime-database
- AngularFire2 - https://github.com/angular/angularfire2
2024-02-04T07:45:49.913Z
nova-2
2-general-nova
2024-01-09.29447
30089e05-99d1-4376-b32e-c263170674af
b50c9b47-f405-4217-af07-ec9af5ad77dd
c683fdb2b5990a56d8ee54ac36fa183646fe284c4c331e79c12ee70f038e3c2e
67875a7f-c9c4-48a0-aa55-5bdb8a91c34a
deprecated
Angular Reactive forms have a useful set of built in validators, but it's not so obvious how you would validate something like username uniqueness when those usernames are saved in an external database such as Firebase.
For something like that, you're going to need to build your own custom asynchronous validator, and and that's exactly what I'm going to show you today.
The validator is going to see if we have any users with a specific username in the Firestore database, and if so, it's going to trigger a reactive validation error, which we can respond to in the front end.
1st, make sure to like and subscribe and grab the source code from angularfirebase.com because you'll be able to use this validator throughout your reactive forms.
We'll get started from a brand new Angular 5 app, and I've installed AngularFire 2.
So follow the install instructions on the official repo.
I've also created a basic sign in component, which is in declarations, and then we're importing the reactive forms module in the import section in addition to our AngularFire dependencies.
In this demo, I'm making the assumption that you have some custom user data saved in the database.
But the validator can work with any type of asynchronous data, whether it's from Firebase or some other source.
If you're brand new to Firestore auth, I recommend starting out with episode 55.
The end result to that lesson is a collection of users in the Firestore database.
Each user document has some custom user information saved about them.
In this case, we have a username, and we want to validate that every new user has a unique username when they sign up.
So so the first thing we need to do is build out to reactive form to collect the user information.
Inside of our component, we import AngularFirestore as well as our reactive form classes.
Then we can inject AngularFirestore and Form Builder in the constructor.
Then to build out a reactive form, all we have to do is declare it as a property and then call form builder group along with our actual form control fields.
We'll go ahead and give it a form field for email.
The first value here is just an empty string, which defines the default value.
Then we can pass it some default validators that we get from Angular.
So this will say that email address is required and then it needs to be in a proper email format.
Then we'll go ahead and do the same thing for username and validate that it's required.
So that just gives us a vanilla reactive form in Angular.
But before we get to the HTML, I wanna give you a tip that will keep your code concise and readable.
I like to set up a getter for each of my form fields because when we get to the HTML, we can just say email rather than having to say this login form get email for each of our validation rules.
HTML forms have a lot of boilerplate markup, so this will just make your life a little bit easier.
Now let's finish out the basic reactive form in the HTML.
First step is to pass our login form to the form group attribute, then we set up a couple input elements and pass in the form control name for its corresponding name.
And that's all it takes to build out a basic reactive form.
Now we're ready to get into the fun stuff.
We're going to jump back into the TypeScript and build our custom asynchronous validator.
To do that, we're going to need map, take, and debounce time from RxJS.
When building a custom validator, it's important to look at the underlying validator interface from Angular.
A validator is just a function that takes a a form control as an argument and then returns either an error object if it's invalid or null if it is valid.
The tricky part for us is that we also have a 3rd party dependency with AngularFirestore.
There are a couple different ways you might handle this, but I think the cleanest way is to create your own custom class and then wrap the validator in a method that takes AngularFirestore as an argument.
This allows us to pass AngularFirestore as an argument rather than trying to bind it in Angular through some other mechanism.
So we have a class called custom validator that has a static method called username that takes AngularFirestore as its argument.
Then we'll go ahead and return a function that adheres to that interface that I showed you just a couple seconds ago.
It takes a form control as the argument.
So we can get the value from the user's form by just calling control value on it.
Username should typically be case insensitive, so we'll make the form value 2 lowercase.
Then we make our validator asynchronous by returning an observable.
We can get our observable from AngularFirestore by calling a f s collection users where the username property equals the username that the user is typing into this form.
That gives us a reference, and then we call value changes to get the observable.
But the problem is we need an observable that completes.
Angular Firestore will just send a continuous stream of data, which doesn't quite work for this validator.
Instead of resolving to either valid or invalid.
It just stays in the pending status.
To solve this problem, we can just pipe in some RxJS operators.
The first one is debounce time, which will delay the query while the user's typing.
Instead of making a query for every keystroke, we'll wait for the user to stop typing for 500 milliseconds and then send the query.
Then to make sure the observable completes, we just call take 1.
Angular Firestore is going to give us back an array, and we can see if that array has any objects in it.
And if so, we know that that username has already been taken.
So we'll map that down to the proper interface by saying, if the array has length, then it's it's going to be an error message.
Otherwise, we're going to return null, which means that the form is valid.
That takes care of our custom validator.
Now we just have to add it to our reactive form.
We just go back up to the form group and add it to the validator's array like we would with any other array, except that we pass it AngularFire restore as an argument.
Now we just need to set up some HTML to give this user some good feedback with this asynchronous validation.
I'm setting up an n g f statement.
And because we have a getter for the username, we can just say username invalid and username dirty.
We'll go ahead and show an error message that username is already taken.
If the username is valid, then we can just show a username is valid message.
And the other possible state is that the validation is pending.
That means the user typed into the form, but we're still waiting on the response from Firestore.
When that's showing, we'll just say hold tight checking availability of that username.
As a final touch, we'll want to disable the form submission when the form is invalid.
So we just bind the form valid or invalid property to the disabled property on the form submission button.
If we start typing into the username field, you can see it brings up that pending message.
And then in this case, Jeff d 23 is already taken because we have an object in that array.
So we get this already taken message.
So you could easily reuse the same logic to validate an email address or anything else that needs to be unique across all of your users in Firestore.
If we start typing again, it goes back into the pending status.
Then a second later, it returns an empty array telling that that username is available.
I'm going to go ahead and wrap up there.
If this video helped you, please like and subscribe.
And if you're serious about building apps with this stack, consider becoming a pro member at angularfirebase.com.
You'll get access to a huge ecosystem of resources designed to help you build and ship production grade apps.
Thanks for watching, and I'll see you soon.

Speaker 0: Angular Reactive forms have a useful set of built in validators, but it's not so obvious how you would validate something like username uniqueness when those usernames are saved in an external database such as Firebase. For something like that, you're going to need to build your own custom asynchronous validator, and and that's exactly what I'm going to show you today. The validator is going to see if we have any users with a specific username in the Firestore database, and if so, it's going to trigger a reactive validation error, which we can respond to in the front end. 1st, make sure to like and subscribe and grab the source code from angularfirebase.com because you'll be able to use this validator throughout your reactive forms. We'll get started from a brand new Angular 5 app, and I've installed AngularFire 2.

So follow the install instructions on the official repo. I've also created a basic sign in component, which is in declarations, and then we're importing the reactive forms module in the import section in addition to our AngularFire dependencies. In this demo, I'm making the assumption that you have some custom user data saved in the database. But the validator can work with any type of asynchronous data, whether it's from Firebase or some other source. If you're brand new to Firestore auth, I recommend starting out with episode 55.

The end result to that lesson is a collection of users in the Firestore database. Each user document has some custom user information saved about them. In this case, we have a username, and we want to validate that every new user has a unique username when they sign up. So so the first thing we need to do is build out to reactive form to collect the user information. Inside of our component, we import AngularFirestore as well as our reactive form classes.

Then we can inject AngularFirestore and Form Builder in the constructor. Then to build out a reactive form, all we have to do is declare it as a property and then call form builder group along with our actual form control fields. We'll go ahead and give it a form field for email. The first value here is just an empty string, which defines the default value. Then we can pass it some default validators that we get from Angular.

So this will say that email address is required and then it needs to be in a proper email format. Then we'll go ahead and do the same thing for username and validate that it's required. So that just gives us a vanilla reactive form in Angular. But before we get to the HTML, I wanna give you a tip that will keep your code concise and readable. I like to set up a getter for each of my form fields because when we get to the HTML, we can just say email rather than having to say this login form get email for each of our validation rules.

HTML forms have a lot of boilerplate markup, so this will just make your life a little bit easier. Now let's finish out the basic reactive form in the HTML. First step is to pass our login form to the form group attribute, then we set up a couple input elements and pass in the form control name for its corresponding name. And that's all it takes to build out a basic reactive form. Now we're ready to get into the fun stuff.

We're going to jump back into the TypeScript and build our custom asynchronous validator. To do that, we're going to need map, take, and debounce time from RxJS. When building a custom validator, it's important to look at the underlying validator interface from Angular. A validator is just a function that takes a a form control as an argument and then returns either an error object if it's invalid or null if it is valid. The tricky part for us is that we also have a 3rd party dependency with AngularFirestore.

There are a couple different ways you might handle this, but I think the cleanest way is to create your own custom class and then wrap the validator in a method that takes AngularFirestore as an argument. This allows us to pass AngularFirestore as an argument rather than trying to bind it in Angular through some other mechanism. So we have a class called custom validator that has a static method called username that takes AngularFirestore as its argument. Then we'll go ahead and return a function that adheres to that interface that I showed you just a couple seconds ago. It takes a form control as the argument.

So we can get the value from the user's form by just calling control value on it. Username should typically be case insensitive, so we'll make the form value 2 lowercase. Then we make our validator asynchronous by returning an observable. We can get our observable from AngularFirestore by calling a f s collection users where the username property equals the username that the user is typing into this form. That gives us a reference, and then we call value changes to get the observable.

But the problem is we need an observable that completes. Angular Firestore will just send a continuous stream of data, which doesn't quite work for this validator. Instead of resolving to either valid or invalid. It just stays in the pending status. To solve this problem, we can just pipe in some RxJS operators.

The first one is debounce time, which will delay the query while the user's typing. Instead of making a query for every keystroke, we'll wait for the user to stop typing for 500 milliseconds and then send the query. Then to make sure the observable completes, we just call take 1. Angular Firestore is going to give us back an array, and we can see if that array has any objects in it. And if so, we know that that username has already been taken.

So we'll map that down to the proper interface by saying, if the array has length, then it's it's going to be an error message. Otherwise, we're going to return null, which means that the form is valid. That takes care of our custom validator. Now we just have to add it to our reactive form. We just go back up to the form group and add it to the validator's array like we would with any other array, except that we pass it AngularFire restore as an argument.

Now we just need to set up some HTML to give this user some good feedback with this asynchronous validation. I'm setting up an n g f statement. And because we have a getter for the username, we can just say username invalid and username dirty. We'll go ahead and show an error message that username is already taken. If the username is valid, then we can just show a username is valid message.

And the other possible state is that the validation is pending. That means the user typed into the form, but we're still waiting on the response from Firestore. When that's showing, we'll just say hold tight checking availability of that username. As a final touch, we'll want to disable the form submission when the form is invalid. So we just bind the form valid or invalid property to the disabled property on the form submission button.

If we start typing into the username field, you can see it brings up that pending message. And then in this case, Jeff d 23 is already taken because we have an object in that array. So we get this already taken message. So you could easily reuse the same logic to validate an email address or anything else that needs to be unique across all of your users in Firestore. If we start typing again, it goes back into the pending status.

Then a second later, it returns an empty array telling that that username is available. I'm going to go ahead and wrap up there. If this video helped you, please like and subscribe. And if you're serious about building apps with this stack, consider becoming a pro member at angularfirebase.com. You'll get access to a huge ecosystem of resources designed to help you build and ship production grade apps.

Thanks for watching, and I'll see you soon.
Angular Reactive forms have a useful set of built in validators, but it's not so obvious how you would validate something like username uniqueness when those usernames are saved in an external database such as Firebase. For something like that, you're going to need to build your own custom asynchronous validator, and and that's exactly what I'm going to show you today. The validator is going to see if we have any users with a specific username in the Firestore database, and if so, it's going to trigger a reactive validation error, which we can respond to in the front end. 1st, make sure to like and subscribe and grab the source code from angularfirebase.com because you'll be able to use this validator throughout your reactive forms. We'll get started from a brand new Angular 5 app, and I've installed AngularFire 2. So follow the install instructions on the official repo. I've also created a basic sign in component, which is in declarations, and then we're importing the reactive forms module in the import section in addition to our AngularFire dependencies.
In this demo, I'm making the assumption that you have some custom user data saved in the database. But the validator can work with any type of asynchronous data, whether it's from Firebase or some other source. If you're brand new to Firestore auth, I recommend starting out with episode 55. The end result to that lesson is a collection of users in the Firestore database. Each user document has some custom user information saved about them. In this case, we have a username, and we want to validate that every new user has a unique username when they sign up.
customers
databases
amazon
data management
So so the first thing we need to do is build out to reactive form to collect the user information. Inside of our component, we import AngularFirestore as well as our reactive form classes. Then we can inject AngularFirestore and Form Builder in the constructor. Then to build out a reactive form, all we have to do is declare it as a property and then call form builder group along with our actual form control fields.
We'll go ahead and give it a form field for email. The first value here is just an empty string, which defines the default value. Then we can pass it some default validators that we get from Angular. So this will say that email address is required and then it needs to be in a proper email format.
email
Then we'll go ahead and do the same thing for username and validate that it's required. So that just gives us a vanilla reactive form in Angular.
But before we get to the HTML, I wanna give you a tip that will keep your code concise and readable. I like to set up a getter for each of my form fields because when we get to the HTML, we can just say email rather than having to say this login form get email for each of our validation rules.
email
HTML forms have a lot of boilerplate markup, so this will just make your life a little bit easier. Now let's finish out the basic reactive form in the HTML. First step is to pass our login form to the form group attribute, then we set up a couple input elements and pass in the form control name for its corresponding name. And that's all it takes to build out a basic reactive form. Now we're ready to get into the fun stuff. We're going to jump back into the TypeScript and build our custom asynchronous validator. To do that, we're going to need map, take, and debounce time from RxJS. When building a custom validator, it's important to look at the underlying validator interface from Angular. A validator is just a function that takes a a form control as an argument and then returns either an error object if it's invalid or null if it is valid. The tricky part for us is that we also have a 3rd party dependency with AngularFirestore. There are a couple different ways you might handle this, but I think the cleanest way is to create your own custom class and then wrap the validator in a method that takes AngularFirestore as an argument. This allows us to pass AngularFirestore as an argument rather than trying to bind it in Angular through some other mechanism. So we have a class called custom validator that has a static method called username that takes AngularFirestore as its argument. Then we'll go ahead and return a function that adheres to that interface that I showed you just a couple seconds ago. It takes a form control as the argument. So we can get the value from the user's form by just calling control value on it. Username should typically be case insensitive, so we'll make the form value 2 lowercase. Then we make our validator asynchronous by returning an observable. We can get our observable from AngularFirestore by calling a f s collection users where the username property equals the username that the user is typing into this form. That gives us a reference, and then we call value changes to get the observable. But the problem is we need an observable that completes. Angular Firestore will just send a continuous stream of data, which doesn't quite work for this validator. Instead of resolving to either valid or invalid. It just stays in the pending status. To solve this problem, we can just pipe in some RxJS operators. The first one is debounce time, which will delay the query while the user's typing. Instead of making a query for every keystroke, we'll wait for the user to stop typing for 500 milliseconds and then send the query. Then to make sure the observable completes, we just call take 1. Angular Firestore is going to give us back an array, and we can see if that array has any objects in it. And if so, we know that that username has already been taken. So we'll map that down to the proper interface by saying, if the array has length, then it's it's going to be an error message. Otherwise, we're going to return null, which means that the form is valid. That takes care of our custom validator. Now we just have to add it to our reactive form. We just go back up to the form group and add it to the validator's array like we would with any other array, except that we pass it AngularFire restore as an argument. Now we just need to set up some HTML to give this user some good feedback with this asynchronous validation. I'm setting up an n g f statement. And because we have a getter for the username, we can just say username invalid and username dirty. We'll go ahead and show an error message that username is already taken. If the username is valid, then we can just show a username is valid message. And the other possible state is that the validation is pending. That means the user typed into the form, but we're still waiting on the response from Firestore. When that's showing, we'll just say hold tight checking availability of that username. As a final touch, we'll want to disable the form submission when the form is invalid. So we just bind the form valid or invalid property to the disabled property on the form submission button. If we start typing into the username field, you can see it brings up that pending message. And then in this case, Jeff d 23 is already taken because we have an object in that array. So we get this already taken message. So you could easily reuse the same logic to validate an email address or anything else that needs to be unique across all of your users in Firestore. If we start typing again, it goes back into the pending status. Then a second later, it returns an empty array telling that that username is available.
I'm going to go ahead and wrap up there. If this video helped you, please like and subscribe. And if you're serious about building apps with this stack, consider becoming a pro member at angularfirebase.com. You'll get access to a huge ecosystem of resources designed to help you build and ship production grade apps. Thanks for watching, and I'll see you soon.
infrastructure
youtube
software
software development
natural resources
Angular Reactive forms have a useful set of built in validators, but it's not so obvious how you would validate something like username uniqueness when those usernames are saved in an external database such as Firebase. For something like that, you're going to need to build your own custom asynchronous validator, and and that's exactly what I'm going to show you today. The validator is going to see if we have any users with a specific username in the Firestore database, and if so, it's going to trigger a reactive validation error, which we can respond to in the front end. 1st, make sure to like and subscribe and grab the source code from angularfirebase.com because you'll be able to use this validator throughout your reactive forms. We'll get started from a brand new Angular 5 app, and I've installed AngularFire 2. So follow the install instructions on the official repo. I've also created a basic sign in component, which is in declarations, and then we're importing the reactive forms module in the import section in addition to our AngularFire dependencies. In this demo, I'm making the assumption that you have some custom user data saved in the database. But the validator can work with any type of asynchronous data, whether it's from Firebase or some other source. If you're brand new to Firestore auth, I recommend starting out with episode 55. The end result to that lesson is a collection of users in the Firestore database. Each user document has some custom user information saved about them. In this case, we have a username, and we want to validate that every new user has a unique username when they sign up. So so the first thing we need to do is build out to reactive form to collect the user information. Inside of our component, we import AngularFirestore as well as our reactive form classes. Then we can inject AngularFirestore and Form Builder in the constructor. Then to build out a reactive form, all we have to do is declare it as a property and then call form builder group along with our actual form control fields. We'll go ahead and give it a form field for email. The first value here is just an empty string, which defines the default value. Then we can pass it some default validators that we get from Angular. So this will say that email address is required and then it needs to be in a proper email format. Then we'll go ahead and do the same thing for username and validate that it's required. So that just gives us a vanilla reactive form in Angular. But before we get to the HTML, I wanna give you a tip that will keep your code concise and readable. I like to set up a getter for each of my form fields because when we get to the HTML, we can just say email rather than having to say this login form get email for each of our validation rules. HTML forms have a lot of boilerplate markup, so this will just make your life a little bit easier. Now let's finish out the basic reactive form in the HTML. First step is to pass our login form to the form group attribute, then we set up a couple input elements and pass in the form control name for its corresponding name. And that's all it takes to build out a basic reactive form. Now we're ready to get into the fun stuff. We're going to jump back into the TypeScript and build our custom asynchronous validator. To do that, we're going to need map, take, and debounce time from RxJS. When building a custom validator, it's important to look at the underlying validator interface from Angular. A validator is just a function that takes a a form control as an argument and then returns either an error object if it's invalid or null if it is valid. The tricky part for us is that we also have a 3rd party dependency with AngularFirestore. There are a couple different ways you might handle this, but I think the cleanest way is to create your own custom class and then wrap the validator in a method that takes AngularFirestore as an argument. This allows us to pass AngularFirestore as an argument rather than trying to bind it in Angular through some other mechanism. So we have a class called custom validator that has a static method called username that takes AngularFirestore as its argument. Then we'll go ahead and return a function that adheres to that interface that I showed you just a couple seconds ago. It takes a form control as the argument. So we can get the value from the user's form by just calling control value on it. Username should typically be case insensitive, so we'll make the form value 2 lowercase. Then we make our validator asynchronous by returning an observable. We can get our observable from AngularFirestore by calling a f s collection users where the username property equals the username that the user is typing into this form. That gives us a reference, and then we call value changes to get the observable. But the problem is we need an observable that completes. Angular Firestore will just send a continuous stream of data, which doesn't quite work for this validator. Instead of resolving to either valid or invalid. It just stays in the pending status. To solve this problem, we can just pipe in some RxJS operators. The first one is debounce time, which will delay the query while the user's typing. Instead of making a query for every keystroke, we'll wait for the user to stop typing for 500 milliseconds and then send the query. Then to make sure the observable completes, we just call take 1. Angular Firestore is going to give us back an array, and we can see if that array has any objects in it. And if so, we know that that username has already been taken. So we'll map that down to the proper interface by saying, if the array has length, then it's it's going to be an error message. Otherwise, we're going to return null, which means that the form is valid. That takes care of our custom validator. Now we just have to add it to our reactive form. We just go back up to the form group and add it to the validator's array like we would with any other array, except that we pass it AngularFire restore as an argument. Now we just need to set up some HTML to give this user some good feedback with this asynchronous validation. I'm setting up an n g f statement. And because we have a getter for the username, we can just say username invalid and username dirty. We'll go ahead and show an error message that username is already taken. If the username is valid, then we can just show a username is valid message. And the other possible state is that the validation is pending. That means the user typed into the form, but we're still waiting on the response from Firestore. When that's showing, we'll just say hold tight checking availability of that username. As a final touch, we'll want to disable the form submission when the form is invalid. So we just bind the form valid or invalid property to the disabled property on the form submission button. If we start typing into the username field, you can see it brings up that pending message. And then in this case, Jeff d 23 is already taken because we have an object in that array. So we get this already taken message. So you could easily reuse the same logic to validate an email address or anything else that needs to be unique across all of your users in Firestore. If we start typing again, it goes back into the pending status. Then a second later, it returns an empty array telling that that username is available. I'm going to go ahead and wrap up there. If this video helped you, please like and subscribe. And if you're serious about building apps with this stack, consider becoming a pro member at angularfirebase.com. You'll get access to a huge ecosystem of resources designed to help you build and ship production grade apps. Thanks for watching, and I'll see you soon.
Angular
angular
Reactive
reactive
forms
forms
have
have
a
a
useful
useful
set
set
of
of
built
built
in
in
validators,
validators
but
but
it's
it's
not
not
so
so
obvious
obvious
how
how
you
you
would
would
validate
validate
something
something
like
like
username
username
uniqueness
uniqueness
when
when
those
those
usernames
usernames
are
are
saved
saved
in
in
an
an
external
external
database
database
such
such
as
as
Firebase.
firebase
For
for
something
something
like
like
that,
that
you're
you're
going
going
to
to
need
need
to
to
build
build
your
your
own
own
custom
custom
asynchronous
asynchronous
validator,
validator
and
and
and
and
that's
that's
exactly
exactly
what
what
I'm
i'm
going
going
to
to
show
show
you
you
today.
today
The
the
validator
validator
is
is
going
going
to
to
see
see
if
if
we
we
have
have
any
any
users
users
with
with
a
a
specific
specific
username
username
in
in
the
the
Firestore
firestore
database,
database
and
and
if
if
so,
so
it's
it's
going
going
to
to
trigger
trigger
a
a
reactive
reactive
validation
validation
error,
error
which
which
we
we
can
can
respond
respond
to
to
in
in
the
the
front
front
end.
end
1st,
1st
make
make
sure
sure
to
to
like
like
and
and
subscribe
subscribe
and
and
grab
grab
the
the
source
source
code
code
from
from
angularfirebase.com
angularfirebase.com
because
because
you'll
you'll
be
be
able
able
to
to
use
use
this
this
validator
validator
throughout
throughout
your
your
reactive
reactive
forms.
forms
We'll
we'll
get
get
started
started
from
from
a
a
brand
brand
new
new
Angular
angular
5
5
app,
app
and
and
I've
i've
installed
installed
AngularFire
angularfire
2.
2
So
so
follow
follow
the
the
install
install
instructions
instructions
on
on
the
the
official
official
repo.
repo
I've
i've
also
also
created
created
a
a
basic
basic
sign
sign
in
in
component,
component
which
which
is
is
in
in
declarations,
declarations
and
and
then
then
we're
we're
importing
importing
the
the
reactive
reactive
forms
forms
module
module
in
in
the
the
import
import
section
section
in
in
addition
addition
to
to
our
our
AngularFire
angularfire
dependencies.
dependencies
In
in
this
this
demo,
demo
I'm
i'm
making
making
the
the
assumption
assumption
that
that
you
you
have
have
some
some
custom
custom
user
user
data
data
saved
saved
in
in
the
the
database.
database
But
but
the
the
validator
validator
can
can
work
work
with
with
any
any
type
type
of
of
asynchronous
asynchronous
data,
data
whether
whether
it's
it's
from
from
Firebase
firebase
or
or
some
some
other
other
source.
source
If
if
you're
you're
brand
brand
new
new
to
to
Firestore
firestore
auth,
auth
I
i
recommend
recommend
starting
starting
out
out
with
with
episode
episode
55.
55
The
the
end
end
result
result
to
to
that
that
lesson
lesson
is
is
a
a
collection
collection
of
of
users
users
in
in
the
the
Firestore
firestore
database.
database
Each
each
user
user
document
document
has
has
some
some
custom
custom
user
user
information
information
saved
saved
about
about
them.
them
In
in
this
this
case,
case
we
we
have
have
a
a
username,
username
and
and
we
we
want
want
to
to
validate
validate
that
that
every
every
new
new
user
user
has
has
a
a
unique
unique
username
username
when
when
they
they
sign
sign
up.
up
So
so
so
so
the
the
first
first
thing
thing
we
we
need
need
to
to
do
do
is
is
build
build
out
out
to
to
reactive
reactive
form
form
to
to
collect
collect
the
the
user
user
information.
information
Inside
inside
of
of
our
our
component,
component
we
we
import
import
AngularFirestore
angularfirestore
as
as
well
well
as
as
our
our
reactive
reactive
form
form
classes.
classes
Then
then
we
we
can
can
inject
inject
AngularFirestore
angularfirestore
and
and
Form
form
Builder
builder
in
in
the
the
constructor.
constructor
Then
then
to
to
build
build
out
out
a
a
reactive
reactive
form,
form
all
all
we
we
have
have
to
to
do
do
is
is
declare
declare
it
it
as
as
a
a
property
property
and
and
then
then
call
call
form
form
builder
builder
group
group
along
along
with
with
our
our
actual
actual
form
form
control
control
fields.
fields
We'll
we'll
go
go
ahead
ahead
and
and
give
give
it
it
a
a
form
form
field
field
for
for
email.
email
The
the
first
first
value
value
here
here
is
is
just
just
an
an
empty
empty
string,
string
which
which
defines
defines
the
the
default
default
value.
value
Then
then
we
we
can
can
pass
pass
it
it
some
some
default
default
validators
validators
that
that
we
we
get
get
from
from
Angular.
angular
So
so
this
this
will
will
say
say
that
that
email
email
address
address
is
is
required
required
and
and
then
then
it
it
needs
needs
to
to
be
be
in
in
a
a
proper
proper
email
email
format.
format
Then
then
we'll
we'll
go
go
ahead
ahead
and
and
do
do
the
the
same
same
thing
thing
for
for
username
username
and
and
validate
validate
that
that
it's
it's
required.
required
So
so
that
that
just
just
gives
gives
us
us
a
a
vanilla
vanilla
reactive
reactive
form
form
in
in
Angular.
angular
But
but
before
before
we
we
get
get
to
to
the
the
HTML,
html
I
i
wanna
wanna
give
give
you
you
a
a
tip
tip
that
that
will
will
keep
keep
your
your
code
code
concise
concise
and
and
readable.
readable
I
i
like
like
to
to
set
set
up
up
a
a
getter
getter
for
for
each
each
of
of
my
my
form
form
fields
fields
because
because
when
when
we
we
get
get
to
to
the
the
HTML,
html
we
we
can
can
just
just
say
say
email
email
rather
rather
than
than
having
having
to
to
say
say
this
this
login
login
form
form
get
get
email
email
for
for
each
each
of
of
our
our
validation
validation
rules.
rules
HTML
html
forms
forms
have
have
a
a
lot
lot
of
of
boilerplate
boilerplate
markup,
markup
so
so
this
this
will
will
just
just
make
make
your
your
life
life
a
a
little
little
bit
bit
easier.
easier
Now
now
let's
let's
finish
finish
out
out
the
the
basic
basic
reactive
reactive
form
form
in
in
the
the
HTML.
html
First
first
step
step
is
is
to
to
pass
pass
our
our
login
login
form
form
to
to
the
the
form
form
group
group
attribute,
attribute
then
then
we
we
set
set
up
up
a
a
couple
couple
input
input
elements
elements
and
and
pass
pass
in
in
the
the
form
form
control
control
name
name
for
for
its
its
corresponding
corresponding
name.
name
And
and
that's
that's
all
all
it
it
takes
takes
to
to
build
build
out
out
a
a
basic
basic
reactive
reactive
form.
form
Now
now
we're
we're
ready
ready
to
to
get
get
into
into
the
the
fun
fun
stuff.
stuff
We're
we're
going
going
to
to
jump
jump
back
back
into
into
the
the
TypeScript
typescript
and
and
build
build
our
our
custom
custom
asynchronous
asynchronous
validator.
validator
To
to
do
do
that,
that
we're
we're
going
going
to
to
need
need
map,
map
take,
take
and
and
debounce
debounce
time
time
from
from
RxJS.
rxjs
When
when
building
building
a
a
custom
custom
validator,
validator
it's
it's
important
important
to
to
look
look
at
at
the
the
underlying
underlying
validator
validator
interface
interface
from
from
Angular.
angular
A
a
validator
validator
is
is
just
just
a
a
function
function
that
that
takes
takes
a
a
a
a
form
form
control
control
as
as
an
an
argument
argument
and
and
then
then
returns
returns
either
either
an
an
error
error
object
object
if
if
it's
it's
invalid
invalid
or
or
null
null
if
if
it
it
is
is
valid.
valid
The
the
tricky
tricky
part
part
for
for
us
us
is
is
that
that
we
we
also
also
have
have
a
a
3rd
3rd
party
party
dependency
dependency
with
with
AngularFirestore.
angularfirestore
There
there
are
are
a
a
couple
couple
different
different
ways
ways
you
you
might
might
handle
handle
this,
this
but
but
I
i
think
think
the
the
cleanest
cleanest
way
way
is
is
to
to
create
create
your
your
own
own
custom
custom
class
class
and
and
then
then
wrap
wrap
the
the
validator
validator
in
in
a
a
method
method
that
that
takes
takes
AngularFirestore
angularfirestore
as
as
an
an
argument.
argument
This
this
allows
allows
us
us
to
to
pass
pass
AngularFirestore
angularfirestore
as
as
an
an
argument
argument
rather
rather
than
than
trying
trying
to
to
bind
bind
it
it
in
in
Angular
angular
through
through
some
some
other
other
mechanism.
mechanism
So
so
we
we
have
have
a
a
class
class
called
called
custom
custom
validator
validator
that
that
has
has
a
a
static
static
method
method
called
called
username
username
that
that
takes
takes
AngularFirestore
angularfirestore
as
as
its
its
argument.
argument
Then
then
we'll
we'll
go
go
ahead
ahead
and
and
return
return
a
a
function
function
that
that
adheres
adheres
to
to
that
that
interface
interface
that
that
I
i
showed
showed
you
you
just
just
a
a
couple
couple
seconds
seconds
ago.
ago
It
it
takes
takes
a
a
form
form
control
control
as
as
the
the
argument.
argument
So
so
we
we
can
can
get
get
the
the
value
value
from
from
the
the
user's
user's
form
form
by
by
just
just
calling
calling
control
control
value
value
on
on
it.
it
Username
username
should
should
typically
typically
be
be
case
case
insensitive,
insensitive
so
so
we'll
we'll
make
make
the
the
form
form
value
value
2
2
lowercase.
lowercase
Then
then
we
we
make
make
our
our
validator
validator
asynchronous
asynchronous
by
by
returning
returning
an
an
observable.
observable
We
we
can
can
get
get
our
our
observable
observable
from
from
AngularFirestore
angularfirestore
by
by
calling
calling
a
a
f
f
s
s
collection
collection
users
users
where
where
the
the
username
username
property
property
equals
equals
the
the
username
username
that
that
the
the
user
user
is
is
typing
typing
into
into
this
this
form.
form
That
that
gives
gives
us
us
a
a
reference,
reference
and
and
then
then
we
we
call
call
value
value
changes
changes
to
to
get
get
the
the
observable.
observable
But
but
the
the
problem
problem
is
is
we
we
need
need
an
an
observable
observable
that
that
completes.
completes
Angular
angular
Firestore
firestore
will
will
just
just
send
send
a
a
continuous
continuous
stream
stream
of
of
data,
data
which
which
doesn't
doesn't
quite
quite
work
work
for
for
this
this
validator.
validator
Instead
instead
of
of
resolving
resolving
to
to
either
either
valid
valid
or
or
invalid.
invalid
It
it
just
just
stays
stays
in
in
the
the
pending
pending
status.
status
To
to
solve
solve
this
this
problem,
problem
we
we
can
can
just
just
pipe
pipe
in
in
some
some
RxJS
rxjs
operators.
operators
The
the
first
first
one
one
is
is
debounce
debounce
time,
time
which
which
will
will
delay
delay
the
the
query
query
while
while
the
the
user's
user's
typing.
typing
Instead
instead
of
of
making
making
a
a
query
query
for
for
every
every
keystroke,
keystroke
we'll
we'll
wait
wait
for
for
the
the
user
user
to
to
stop
stop
typing
typing
for
for
500
500
milliseconds
milliseconds
and
and
then
then
send
send
the
the
query.
query
Then
then
to
to
make
make
sure
sure
the
the
observable
observable
completes,
completes
we
we
just
just
call
call
take
take
1.
1
Angular
angular
Firestore
firestore
is
is
going
going
to
to
give
give
us
us
back
back
an
an
array,
array
and
and
we
we
can
can
see
see
if
if
that
that
array
array
has
has
any
any
objects
objects
in
in
it.
it
And
and
if
if
so,
so
we
we
know
know
that
that
that
that
username
username
has
has
already
already
been
been
taken.
taken
So
so
we'll
we'll
map
map
that
that
down
down
to
to
the
the
proper
proper
interface
interface
by
by
saying,
saying
if
if
the
the
array
array
has
has
length,
length
then
then
it's
it's
it's
it's
going
going
to
to
be
be
an
an
error
error
message.
message
Otherwise,
otherwise
we're
we're
going
going
to
to
return
return
null,
null
which
which
means
means
that
that
the
the
form
form
is
is
valid.
valid
That
that
takes
takes
care
care
of
of
our
our
custom
custom
validator.
validator
Now
now
we
we
just
just
have
have
to
to
add
add
it
it
to
to
our
our
reactive
reactive
form.
form
We
we
just
just
go
go
back
back
up
up
to
to
the
the
form
form
group
group
and
and
add
add
it
it
to
to
the
the
validator's
validator's
array
array
like
like
we
we
would
would
with
with
any
any
other
other
array,
array
except
except
that
that
we
we
pass
pass
it
it
AngularFire
angularfire
restore
restore
as
as
an
an
argument.
argument
Now
now
we
we
just
just
need
need
to
to
set
set
up
up
some
some
HTML
html
to
to
give
give
this
this
user
user
some
some
good
good
feedback
feedback
with
with
this
this
asynchronous
asynchronous
validation.
validation
I'm
i'm
setting
setting
up
up
an
an
n
n
g
g
f
f
statement.
statement
And
and
because
because
we
we
have
have
a
a
getter
getter
for
for
the
the
username,
username
we
we
can
can
just
just
say
say
username
username
invalid
invalid
and
and
username
username
dirty.
dirty
We'll
we'll
go
go
ahead
ahead
and
and
show
show
an
an
error
error
message
message
that
that
username
username
is
is
already
already
taken.
taken
If
if
the
the
username
username
is
is
valid,
valid
then
then
we
we
can
can
just
just
show
show
a
a
username
username
is
is
valid
valid
message.
message
And
and
the
the
other
other
possible
possible
state
state
is
is
that
that
the
the
validation
validation
is
is
pending.
pending
That
that
means
means
the
the
user
user
typed
typed
into
into
the
the
form,
form
but
but
we're
we're
still
still
waiting
waiting
on
on
the
the
response
response
from
from
Firestore.
firestore
When
when
that's
that's
showing,
showing
we'll
we'll
just
just
say
say
hold
hold
tight
tight
checking
checking
availability
availability
of
of
that
that
username.
username
As
as
a
a
final
final
touch,
touch
we'll
we'll
want
want
to
to
disable
disable
the
the
form
form
submission
submission
when
when
the
the
form
form
is
is
invalid.
invalid
So
so
we
we
just
just
bind
bind
the
the
form
form
valid
valid
or
or
invalid
invalid
property
property
to
to
the
the
disabled
disabled
property
property
on
on
the
the
form
form
submission
submission
button.
button
If
if
we
we
start
start
typing
typing
into
into
the
the
username
username
field,
field
you
you
can
can
see
see
it
it
brings
brings
up
up
that
that
pending
pending
message.
message
And
and
then
then
in
in
this
this
case,
case
Jeff
jeff
d
d
23
23
is
is
already
already
taken
taken
because
because
we
we
have
have
an
an
object
object
in
in
that
that
array.
array
So
so
we
we
get
get
this
this
already
already
taken
taken
message.
message
So
so
you
you
could
could
easily
easily
reuse
reuse
the
the
same
same
logic
logic
to
to
validate
validate
an
an
email
email
address
address
or
or
anything
anything
else
else
that
that
needs
needs
to
to
be
be
unique
unique
across
across
all
all
of
of
your
your
users
users
in
in
Firestore.
firestore
If
if
we
we
start
start
typing
typing
again,
again
it
it
goes
goes
back
back
into
into
the
the
pending
pending
status.
status
Then
then
a
a
second
second
later,
later
it
it
returns
returns
an
an
empty
empty
array
array
telling
telling
that
that
that
that
username
username
is
is
available.
available
I'm
i'm
going
going
to
to
go
go
ahead
ahead
and
and
wrap
wrap
up
up
there.
there
If
if
this
this
video
video
helped
helped
you,
you
please
please
like
like
and
and
subscribe.
subscribe
And
and
if
if
you're
you're
serious
serious
about
about
building
building
apps
apps
with
with
this
this
stack,
stack
consider
consider
becoming
becoming
a
a
pro
pro
member
member
at
at
angularfirebase.com.
angularfirebase.com
You'll
you'll
get
get
access
access
to
to
a
a
huge
huge
ecosystem
ecosystem
of
of
resources
resources
designed
designed
to
to
help
help
you
you
build
build
and
and
ship
ship
production
production
grade
grade
apps.
apps
Thanks
thanks
for
for
watching,
watching
and
and
I'll
i'll
see
see
you
you
soon.
soon
success
The use of Angular Reactive forms for validating user usernames and triggering reactive validation errors is discussed, along with instructions on import and configure forms modules and creating custom asynchronous method for each form field. A tip is given on how to keep the code concise and readable, and how to set up a custom asynchronous method for emails. The speaker also explains how to use the RxJS operator to handle the output of the method and suggests becoming a pro member if building apps is a priority.
Async Validation with Angular Reactive Forms + Firebase
Angular Reactive forms have a useful set of built in validators, but it's not so obvious how you would validate something like username uniqueness when those usernames are saved in an external database such as Firebase. For something like that, you're going to need to build your own custom asynchronous validator, and and that's exactly what I'm going to show you today. The validator is going to see if we have any users with a specific username in the Firestore database, and if so, it's going to trigger a reactive validation error, which we can respond to in the front end. 1st, make sure to like and subscribe and grab the source code from angularfirebase.com because you'll be able to use this validator throughout your reactive forms. We'll get started from a brand new Angular 5 app, and I've installed AngularFire 2. So follow the install instructions on the official repo. I've also created a basic sign in component, which is in declarations, and then we're importing the reactive forms module in the import section in addition to our AngularFire dependencies. In this demo, I'm making the assumption that you have some custom user data saved in the database. But the validator can work with any type of asynchronous data, whether it's from Firebase or some other source. If you're brand new to Firestore auth, I recommend starting out with episode 55. The end result to that lesson is a collection of users in the Firestore database. Each user document has some custom user information saved about them. In this case, we have a username, and we want to validate that every new user has a unique username when they sign up. So so the first thing we need to do is build out to reactive form to collect the user information. Inside of our component, we import AngularFirestore as well as our reactive form classes. Then we can inject AngularFirestore and Form Builder in the constructor. Then to build out a reactive form, all we have to do is declare it as a property and then call form builder group along with our actual form control fields. We'll go ahead and give it a form field for email. The first value here is just an empty string, which defines the default value. Then we can pass it some default validators that we get from Angular. So this will say that email address is required and then it needs to be in a proper email format. Then we'll go ahead and do the same thing for username and validate that it's required. So that just gives us a vanilla reactive form in Angular. But before we get to the HTML, I wanna give you a tip that will keep your code concise and readable. I like to set up a getter for each of my form fields because when we get to the HTML, we can just say email rather than having to say this login form get email for each of our validation rules. HTML forms have a lot of boilerplate markup, so this will just make your life a little bit easier. Now let's finish out the basic reactive form in the HTML. First step is to pass our login form to the form group attribute, then we set up a couple input elements and pass in the form control name for its corresponding name. And that's all it takes to build out a basic reactive form. Now we're ready to get into the fun stuff. We're going to jump back into the TypeScript and build our custom asynchronous validator. To do that, we're going to need map, take, and debounce time from RxJS. When building a custom validator, it's important to look at the underlying validator interface from Angular. A validator is just a function that takes a a form control as an argument and then returns either an error object if it's invalid or null if it is valid. The tricky part for us is that we also have a 3rd party dependency with AngularFirestore. There are a couple different ways you might handle this, but I think the cleanest way is to create your own custom class and then wrap the validator in a method that takes AngularFirestore as an argument. This allows us to pass AngularFirestore as an argument rather than trying to bind it in Angular through some other mechanism. So we have a class called custom validator that has a static method called username that takes AngularFirestore as its argument. Then we'll go ahead and return a function that adheres to that interface that I showed you just a couple seconds ago. It takes a form control as the argument. So we can get the value from the user's form by just calling control value on it. Username should typically be case insensitive, so we'll make the form value 2 lowercase. Then we make our validator asynchronous by returning an observable. We can get our observable from AngularFirestore by calling a f s collection users where the username property equals the username that the user is typing into this form. That gives us a reference, and then we call value changes to get the observable. But the problem is we need an observable that completes. Angular Firestore will just send a continuous stream of data, which doesn't quite work for this validator. Instead of resolving to either valid or invalid. It just stays in the pending status. To solve this problem, we can just pipe in some RxJS operators. The first one is debounce time, which will delay the query while the user's typing. Instead of making a query for every keystroke, we'll wait for the user to stop typing for 500 milliseconds and then send the query. Then to make sure the observable completes, we just call take 1. Angular Firestore is going to give us back an array, and we can see if that array has any objects in it. And if so, we know that that username has already been taken. So we'll map that down to the proper interface by saying, if the array has length, then it's it's going to be an error message. Otherwise, we're going to return null, which means that the form is valid. That takes care of our custom validator. Now we just have to add it to our reactive form. We just go back up to the form group and add it to the validator's array like we would with any other array, except that we pass it AngularFire restore as an argument. Now we just need to set up some HTML to give this user some good feedback with this asynchronous validation. I'm setting up an n g f statement. And because we have a getter for the username, we can just say username invalid and username dirty. We'll go ahead and show an error message that username is already taken. If the username is valid, then we can just show a username is valid message. And the other possible state is that the validation is pending. That means the user typed into the form, but we're still waiting on the response from Firestore. When that's showing, we'll just say hold tight checking availability of that username. As a final touch, we'll want to disable the form submission when the form is invalid. So we just bind the form valid or invalid property to the disabled property on the form submission button. If we start typing into the username field, you can see it brings up that pending message. And then in this case, Jeff d 23 is already taken because we have an object in that array. So we get this already taken message. So you could easily reuse the same logic to validate an email address or anything else that needs to be unique across all of your users in Firestore. If we start typing again, it goes back into the pending status. Then a second later, it returns an empty array telling that that username is available. I'm going to go ahead and wrap up there. If this video helped you, please like and subscribe. And if you're serious about building apps with this stack, consider becoming a pro member at angularfirebase.com. You'll get access to a huge ecosystem of resources designed to help you build and ship production grade apps. Thanks for watching, and I'll see you soon.
The use of Angular Reactive forms for validating user usernames and triggering reactive validation errors is discussed, along with instructions on import and configure forms modules and creating custom asynchronous method for each form field. A tip is given on how to keep the code concise and readable, and how to set up a custom asynchronous method for emails. The speaker also explains how to use the RxJS operator to handle the output of the method and suggests becoming a pro member if building apps is a priority.