Coding

Auth State Feedback with Vuex | Vue.js + Vuetify + Firebase FULL PROJECT

  • 00:00:01 in our view the five firebase meter
  • 00:00:04 project here we already achieved a lot
  • 00:00:07 and over the last videos we implemented
  • 00:00:10 authentication we're now able to sign
  • 00:00:12 users app and in the one problem we
  • 00:00:16 still have there is we don't really
  • 00:00:17 communicate the current state of our
  • 00:00:20 authentication though so click sign up
  • 00:00:22 here well I get this automatically
  • 00:00:24 generated html5 error but we don't get
  • 00:00:28 any error besides debt if I sign up with
  • 00:00:31 a valid form data but a password which
  • 00:00:34 actually is not long enough I don't get
  • 00:00:36 any feedback at all so that is not the
  • 00:00:39 best way of handling this form what be
  • 00:00:41 nice to see when something is happening
  • 00:00:43 would be nice to get some authentication
  • 00:00:46 errors for example let's implement that
  • 00:00:49 in this video
  • 00:00:53 so I want to basically display the
  • 00:00:57 current state or information about the
  • 00:00:59 current state of indication to the user
  • 00:01:02 for that we of course will use UX
  • 00:01:05 instance our state management system and
  • 00:01:08 there I want to track two things I want
  • 00:01:11 to track if we're currently loading data
  • 00:01:14 so if I want to display like a spinner
  • 00:01:16 because we're currently sending data to
  • 00:01:18 the server and waiting for a response
  • 00:01:19 and I want to display if we get any
  • 00:01:22 authentication errors now for that I'll
  • 00:01:25 simply go up in my state and here
  • 00:01:29 besides my loaded meetups on the user
  • 00:01:31 I'll add cue other things I'll add a new
  • 00:01:34 field which is called loading which will
  • 00:01:37 set to false initially because initially
  • 00:01:39 we are loading and then I'll also have a
  • 00:01:43 field of error which I'll set to null
  • 00:01:45 because initially I also don't assume to
  • 00:01:48 have an off error now we could of course
  • 00:01:51 also just name this error for now and
  • 00:01:54 later see if we can reuse that on
  • 00:01:56 different components because we might
  • 00:01:58 have different areas in our application
  • 00:02:00 where we reach out to a server and then
  • 00:02:02 it might be nice to have a reusable
  • 00:02:03 error state we can use so with these two
  • 00:02:07 new state fields here I need new
  • 00:02:11 mutations to change them for example I
  • 00:02:14 want to have a set loading mutation
  • 00:02:17 where I of course mutates the state and
  • 00:02:19 when I get a payload to either set it to
  • 00:02:22 loading or to well to not loading
  • 00:02:24 because we are done we got everything we
  • 00:02:26 want so here I will simply set state
  • 00:02:30 loading equal to payload so payload
  • 00:02:33 should be true or false depending on
  • 00:02:35 whether we are loading or not so thatís
  • 00:02:38 what I'll set up here and then I also
  • 00:02:41 want to have a set error commit mutation
  • 00:02:47 that is what's called here I also
  • 00:02:49 receive a payload and that of course
  • 00:02:50 will be my error so we'll set state
  • 00:02:53 error equal to payload that would be a
  • 00:02:57 fitting mutation we could also add a
  • 00:03:00 clear error mutation and of course you
  • 00:03:04 could all just pass a payload of null
  • 00:03:06 here clear
  • 00:03:07 error but I think it is a bit more
  • 00:03:10 explicit about what we do here if we
  • 00:03:12 have a mutation really focusing on this
  • 00:03:15 sole purpose where I said state error
  • 00:03:18 equal to null so with that we got new
  • 00:03:22 mutations to work with loading and error
  • 00:03:25 states now we can use them for example
  • 00:03:28 in signing a user up right at the start
  • 00:03:31 of course once it's said loading to true
  • 00:03:33 because no matter if it succeeds or not
  • 00:03:35 we are loading we are reaching out to
  • 00:03:38 the web so here it is action I
  • 00:03:42 definitely want to commit set loading
  • 00:03:45 and I want to set this to true because I
  • 00:03:48 am loading on the other hand whenever we
  • 00:03:52 reach the better block here where we got
  • 00:03:55 a user we certainly are not loading any
  • 00:03:57 more so here we can again commit set
  • 00:04:00 loading but here set it to false and of
  • 00:04:03 course I also want to set loading to
  • 00:04:05 false if we get an error because even
  • 00:04:07 though we got an error the loading
  • 00:04:09 process is finished there's no more data
  • 00:04:11 to come on the other hand if we do get
  • 00:04:14 an error there's one other thing I want
  • 00:04:15 to commit I want to set set error queue
  • 00:04:19 error and this specific error here
  • 00:04:22 thrown by firebase happens to have a
  • 00:04:25 message property we could see that in
  • 00:04:28 one of the earlier videos and you can
  • 00:04:30 confirm that if you assembly run
  • 00:04:33 authentication open the console each our
  • 00:04:35 script console because we are logging
  • 00:04:37 the error here and then have a look at
  • 00:04:39 the error so there we have a message
  • 00:04:41 property the following one here let me
  • 00:04:45 show this to you if we enter valid data
  • 00:04:48 by the password which is not long enough
  • 00:04:50 and I click sign up here we got a
  • 00:04:52 message object as you can see password
  • 00:04:55 should at least be 6 characters so this
  • 00:04:57 is the property we can access there and
  • 00:05:00 that's the one we'll then use so that's
  • 00:05:03 something we have to rely on so with
  • 00:05:04 that I'm also saving the error on the
  • 00:05:07 other hand right at the start when we
  • 00:05:09 start loading we probably want to also
  • 00:05:13 run clear error so this mutation here
  • 00:05:17 because if you're sending a new request
  • 00:05:20 we want you
  • 00:05:21 here any previous barrows probably so
  • 00:05:23 that looks like a good a decent setup
  • 00:05:25 here of course I'll repeat it for
  • 00:05:29 designing process are all the commit
  • 00:05:32 loading and clear errors here at the
  • 00:05:34 beginning all set
  • 00:05:36 loading to false once we have well
  • 00:05:39 either a success or an error case but I
  • 00:05:42 will also set the air or here like that
  • 00:05:45 with that we're managing all that in
  • 00:05:47 view X we're managing our state here now
  • 00:05:50 we have to take advantage of the state
  • 00:05:51 in our views for example to show a
  • 00:05:54 spinner whilst we are loading or to show
  • 00:05:57 an error if we got one let's start with
  • 00:06:00 the error and for that let's go back to
  • 00:06:05 beautify chess and here under components
  • 00:06:08 this alert component looks alright we
  • 00:06:11 can add such an alert at the top of our
  • 00:06:13 page to show it whenever we got an error
  • 00:06:16 actually I want to have a closeable
  • 00:06:18 alert though so that we can dismiss it
  • 00:06:20 as a user and we can simply have a look
  • 00:06:22 at the code here as always we see the
  • 00:06:24 alert is the component this mis'able has
  • 00:06:27 to be added so that we get this X symbol
  • 00:06:29 to close it and then we bind it either
  • 00:06:33 to the model to open close it's
  • 00:06:35 triggered by a property or since we
  • 00:06:38 model it's just a wrapper for an input
  • 00:06:40 event which is emitted and a valuable
  • 00:06:42 property you can pass in we might also
  • 00:06:45 just listen to the input event to clear
  • 00:06:48 our errors but I'll come back to that
  • 00:06:50 let me copy that code here and I want to
  • 00:06:53 add it in my signup W file here at the
  • 00:06:56 very top I want to do the same in my
  • 00:06:59 sign-in file so why don't we create a
  • 00:07:02 utility component for that stored in a
  • 00:07:04 new directory maybe all name is shared
  • 00:07:07 because will hold some shared components
  • 00:07:09 and here I'll name it alert that view
  • 00:07:12 was the file name and here I'll add a
  • 00:07:15 template like that and injured it like
  • 00:07:20 that so now we got the alert here now
  • 00:07:24 with that I want to set this from info
  • 00:07:27 to let's have a look
  • 00:07:29 maybe yeah the error alert so that has
  • 00:07:32 the error property then on it so that
  • 00:07:35 you error dismissible and I don't want
  • 00:07:38 to use the model instead I want you just
  • 00:07:41 listen to the event and bind it through
  • 00:07:45 a different source
  • 00:07:46 so here I'll add a script and on this
  • 00:07:53 script here or in this script
  • 00:07:57 I'll now export my default object as
  • 00:07:59 always and here I'll simply add a method
  • 00:08:03 on clothes where I will omit a new event
  • 00:08:08 with this dollar sign eMED emit using
  • 00:08:11 this built-in event emitter you chase
  • 00:08:13 offers and I will name it dismissed you
  • 00:08:16 can choose any name you want here and
  • 00:08:18 that's actually all I won't pass any
  • 00:08:20 data with that now here I don't use the
  • 00:08:24 model therefore but I just mind you add
  • 00:08:26 input and here I then execute on clothes
  • 00:08:31 like that now let's see if that works
  • 00:08:35 like that if I go to the signup to view
  • 00:08:37 file here I'll add and UV layout row at
  • 00:08:40 very top where I will hold this alert
  • 00:08:43 later on with a reflex element X as 12
  • 00:08:48 and on smaller screens it should also be
  • 00:08:51 a bit smaller and in there and I want to
  • 00:08:54 include that alert component I will make
  • 00:08:56 it a global component so in the main dot
  • 00:08:58 JS file I'll first of all import it so
  • 00:09:02 I'll alert import the alert component
  • 00:09:05 from dot slash components shared and
  • 00:09:10 then the alert stop you file like that
  • 00:09:12 and with that being imported I can now
  • 00:09:15 register it here with view component and
  • 00:09:19 then I'll name it app alert the alert
  • 00:09:23 component like that so that's the
  • 00:09:27 component registered we can now use that
  • 00:09:29 selector here and you sign up as view
  • 00:09:31 file to import it like this and here I
  • 00:09:34 now want to listen to the dismissed
  • 00:09:36 event that's the custom event we're
  • 00:09:39 emitting here like this happens or this
  • 00:09:41 is emitted if we actually do
  • 00:09:42 miss the alert so here I want to listen
  • 00:09:46 to that and I want to execute on
  • 00:09:48 dismissed a method which I of course
  • 00:09:51 have to implement here and yes you could
  • 00:09:54 do that differently I'm just using this
  • 00:09:56 setup because theoretically with that
  • 00:09:58 you could use that alert component here
  • 00:10:00 to not just display errors but anything
  • 00:10:03 which can be dismissed and if I were to
  • 00:10:05 handle on clothes in here in the alert
  • 00:10:07 component and reach out to view X to
  • 00:10:10 clear errors then this alert would be
  • 00:10:12 bound to only handle errors because it
  • 00:10:15 manipulates the state instead this is a
  • 00:10:18 dump component it doesn't know what I
  • 00:10:20 use it for and yes you will have to
  • 00:10:22 adjust your text view output here but
  • 00:10:24 with that this also means you can use it
  • 00:10:27 by simply adding or omitting this
  • 00:10:29 dismissed event and then we handle on
  • 00:10:31 this mist in the component where we know
  • 00:10:33 what we actually want to display so here
  • 00:10:36 I'll add a new method on dismissed and
  • 00:10:39 for now I will simply log it to see if
  • 00:10:43 that works
  • 00:10:43 dismissed alert now right now if we go
  • 00:10:48 to the signup page again and we load
  • 00:10:53 this we should always see the alert we
  • 00:10:56 don't I'm including Yeller here well yes
  • 00:11:00 make sense by default it's not showing
  • 00:11:02 so here we have to sum a binary value
  • 00:11:05 property either to true or false so bind
  • 00:11:08 with a colon in front of it to bind it
  • 00:11:10 to a dynamic value and it should always
  • 00:11:13 be true here though because I always
  • 00:11:15 want to show it now we see the error
  • 00:11:18 here now if I click on that we see this
  • 00:11:23 missed alert whenever I click it so
  • 00:11:25 that's working with that we got the
  • 00:11:27 logic we need to now also control when
  • 00:11:30 we show it and I won't trigger that here
  • 00:11:33 through value even though I could do
  • 00:11:35 that but I can simply decide if I want
  • 00:11:38 to attach this whole row here with vs
  • 00:11:41 and there I now need to track we have an
  • 00:11:44 error or not so for that let's go back
  • 00:11:47 to the store and add a gather and here
  • 00:11:50 I'll name this error I'll of course
  • 00:11:55 X
  • 00:11:55 state here and I will return state error
  • 00:11:58 just like that whilst of already here I
  • 00:12:01 can also return load in here because
  • 00:12:04 that's the other news state we added an
  • 00:12:06 L needed is to return state loading like
  • 00:12:10 that so now I'm returning the error back
  • 00:12:13 can you sign up a view file I can now
  • 00:12:15 add a new computed property which I'll
  • 00:12:18 also name error because here I will
  • 00:12:21 return this store gathers error so the
  • 00:12:25 error we just added with that error
  • 00:12:28 property here this is now what I want to
  • 00:12:31 bind here if that is no it will not be
  • 00:12:34 displayed if it's anything but now we
  • 00:12:36 will see the error now in on this missed
  • 00:12:39 I therefore here one to dispatch a new
  • 00:12:42 action this store dispatch clear error
  • 00:12:47 of course because I want to get rid of
  • 00:12:50 the error if I get rid of the error the
  • 00:12:52 error getter will return null again and
  • 00:12:54 that will then trigger we if to remove
  • 00:12:57 this road and therefore the alert and it
  • 00:13:00 will reappear if we get a new error now
  • 00:13:03 of course I want to pass the error text
  • 00:13:05 into that alert component so I will bind
  • 00:13:08 with call and text to a text property
  • 00:13:12 and pass error that message keep in mind
  • 00:13:15 error has to be object which has a
  • 00:13:18 message that's just something I define
  • 00:13:21 in my application it's even now in which
  • 00:13:23 case the thousand get executed because
  • 00:13:25 the whole row isn't attached or it is
  • 00:13:28 not object and in this case it needs to
  • 00:13:30 have a message property now of course
  • 00:13:33 the problem is that app alert doesn't
  • 00:13:36 know a text property we could bind to so
  • 00:13:39 we have to go to alert and add it why
  • 00:13:41 are the props property here I want to
  • 00:13:45 bind to a text property which I then
  • 00:13:48 output here inside of my alert like this
  • 00:13:51 with this setup let's save this and
  • 00:13:53 let's see if it works let's open the
  • 00:13:55 console enter something here like an
  • 00:13:59 invalid password and let's click signup
  • 00:14:01 and we do get the error here password
  • 00:14:05 should be at least 6 characters close
  • 00:14:07 this
  • 00:14:08 then we get an error unknown action-type
  • 00:14:11 clear error let's see did I miss type
  • 00:14:14 that the action is named the action
  • 00:14:19 doesn't exist we only have the mutation
  • 00:14:21 right
  • 00:14:21 so I obviously need to add it as action
  • 00:14:25 to clear error because I'm dispatching
  • 00:14:28 it as action and I want you to do that
  • 00:14:31 so here all extract commit again and
  • 00:14:35 here I will then commit clear error like
  • 00:14:42 that I didn't have to do that for set
  • 00:14:45 error because right now I'm only
  • 00:14:47 committing set error here as part of
  • 00:14:49 other actions which is fine so now we
  • 00:14:51 have a clear error action let's try it
  • 00:14:54 again let's maybe try a valid password
  • 00:14:56 for the email address which is already
  • 00:14:58 taken and we see the email address is
  • 00:15:01 already in use by another account so
  • 00:15:02 it's really nice that firebase gives us
  • 00:15:04 this nicely formatted error messages now
  • 00:15:07 closing also works they submit again I
  • 00:15:11 get it again so that's nice as a last
  • 00:15:14 piece in this video I want to disable
  • 00:15:17 the button and show a spinner inside the
  • 00:15:19 button whilst we are waiting for the
  • 00:15:22 response and the cool thing is beautify
  • 00:15:25 actually makes that simple if you check
  • 00:15:27 out the button configuration here and
  • 00:15:29 you scroll down a little bit you will
  • 00:15:32 see that you have loaders which are
  • 00:15:34 buttons you can click queue for example
  • 00:15:37 see a spinner here here the icon loader
  • 00:15:40 jitter looks pretty good so let's
  • 00:15:42 inspect that code and you see that I can
  • 00:15:45 loader your uses disks and with a loader
  • 00:15:48 icon side of it and then also simply
  • 00:15:53 gets disabled when it is loading and
  • 00:15:55 binds to loading property when it is
  • 00:15:57 loading so that is what I need to
  • 00:16:00 implement I'll do that you signup to
  • 00:16:03 view file here in my button where I have
  • 00:16:05 sign up right now I'll add something
  • 00:16:08 after sign up this span I copied here so
  • 00:16:12 this span which will actually display DD
  • 00:16:16 spinning circle whenever it is loading
  • 00:16:20 so like that
  • 00:16:22 I also now of course need to bind to
  • 00:16:26 disable and to loading when it is
  • 00:16:28 loading and for that I will bind to a
  • 00:16:30 loading property so loading will be
  • 00:16:33 bound to loading and loading here is
  • 00:16:36 just a property made available by the V
  • 00:16:38 button element whilst loading here is a
  • 00:16:40 property I have to define and I will
  • 00:16:43 define it as a computed property because
  • 00:16:46 where will I get loading where will I
  • 00:16:48 get this information if it's loading
  • 00:16:50 from from my view X state right because
  • 00:16:54 here we have that state or use the
  • 00:16:57 mutation here's the loading state and we
  • 00:17:00 set it to loading or to not loading in
  • 00:17:03 our actions depending on whether we're
  • 00:17:05 just starting or finishing so I can use
  • 00:17:08 that information extracted here from the
  • 00:17:10 Gator we also defined this store gathers
  • 00:17:14 loading that's now referring to that
  • 00:17:18 Gator we define down here to get that
  • 00:17:21 loading state and with that we got
  • 00:17:23 everything we need now let's try it out
  • 00:17:26 let's go back to the application here
  • 00:17:28 let's reload it maybe and let's try this
  • 00:17:31 again let's submit a valid value here
  • 00:17:34 click sign up yeah we saw it but let's
  • 00:17:40 try it invalid one again it's not
  • 00:17:43 spinning whoops let me quickly enter
  • 00:17:45 some invalid values it's not spinning
  • 00:17:47 the reason for this is that we didn't
  • 00:17:50 copy all the code here just loading the
  • 00:17:54 HTML code isn't enough notice the custom
  • 00:17:58 loader class that isn't provided by
  • 00:18:00 beautify by default instead you see the
  • 00:18:03 style tab here here if you CSS code you
  • 00:18:07 rarely have to do that but some
  • 00:18:09 component examples here use as CSS code
  • 00:18:13 so always check all the tabs here if
  • 00:18:15 something isn't working so in this case
  • 00:18:18 I'll just copy the style here and I
  • 00:18:21 could copy it into my signup the view
  • 00:18:22 file but I actually want to use the same
  • 00:18:25 logic and logic in different places so
  • 00:18:28 all instead use my main dot stylist file
  • 00:18:31 where I change the theme
  • 00:18:33 and here you cannot actually just copy
  • 00:18:35 in normal CSS code you don't have to use
  • 00:18:38 stylus syntax that will work so I'm now
  • 00:18:41 I'm defining the custom loaded class
  • 00:18:43 globally and with dead if we now let it
  • 00:18:47 compile we try this again now you see
  • 00:18:51 spend firebase is just so super quick
  • 00:18:53 that you don't really see but if you
  • 00:18:55 watch closely it does spin before we get
  • 00:18:57 the error so that's nice let's now do
  • 00:19:00 the same for these sign-in page that
  • 00:19:02 should of course be simple we got the
  • 00:19:04 logic in this signup page I'll first of
  • 00:19:07 all copy the whole button here go over
  • 00:19:10 to sign in and replace the button here
  • 00:19:13 just make sure to rename it to sign-in
  • 00:19:15 and what else did we change
  • 00:19:18 well we added that alert at the top so
  • 00:19:20 let's add the layout that row with the
  • 00:19:23 alert at the top of that form too so
  • 00:19:26 right after the initial container the
  • 00:19:29 missing thing now is that we need to get
  • 00:19:31 the computed properties so loading and
  • 00:19:34 error and that we'll need to add the on
  • 00:19:37 dismiss method so I'll do that
  • 00:19:39 in sign in got view here first of all
  • 00:19:42 add my Q computed properties and all the
  • 00:19:47 copied on dismissed method from the
  • 00:19:49 signup to view file and add it here in
  • 00:19:52 on sign in the sign in to view file I
  • 00:19:56 can get rid of the console log with the
  • 00:19:58 dismissed error I guess so let's save
  • 00:20:01 this and let's try it out that should be
  • 00:20:03 all and that shows how reusable that
  • 00:20:05 alert component already is here on the
  • 00:20:09 sign-in page if we reload this and we
  • 00:20:11 well try to sign in with something which
  • 00:20:14 doesn't exist like test for didn't
  • 00:20:17 create that there isn't a user that's
  • 00:20:19 that's great and if we use a valid email
  • 00:20:21 address but a wrong password well either
  • 00:20:26 the user is invalid or the password so
  • 00:20:28 we get an error message here Q and we
  • 00:20:31 can dismiss it now let's try a valid
  • 00:20:33 login data attempt here that's still
  • 00:20:37 working so with that we enhance the the
  • 00:20:41 off process we're using this space now
  • 00:20:43 we're giving a better feedback to the
  • 00:20:45 user
  • 00:20:46 super important any application because
  • 00:20:48 you obviously want to allow the user to
  • 00:20:50 know where he is and what's happening I
  • 00:20:53 hope this was helpful
  • 00:20:54 can't wait to see you the other videos
  • 00:20:56 bye