CanDeactivate Guard in Angular Router (2021)

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
hi everyone another tuesday another video on decoded frontend channel my name is mitch omarzanski and i hope you're pretty excited today because we continue to talk about angular router guards and today i'm gonna show you how to create and how to use can deactivate router guard so stay here and let's get started but okay so what does this can deactivate router guard connect can deactivate order guard involves some logic before we trying to leave some certain road and destroy the component associated with it so basically this is opposite what can activate does which involves some logic before we try to create component for some associated rotor however if you hear first time about can activate rotor guard or router guards itself i would recommend you to check out my previous video exactly about this topic so you can do it a bit later but let's continue when would we need uh such a scenario where we want to check if we want to destroy component or not well you can imagine just a huge form yeah which you we usually fill out so we can uh we should put their name surname address whatever hundreds of fields very complex form and imagine the situation that incidentally you leave this page and when you go back the data you entered disappeared this is extremely bad user experience and you know data which user enters in your forms this is the most important data you have to care about safety of this data as much as possible and connect the activate guard can help you with this because before you navigate from this form you can check if this form is saved or not and then if it's saved you can allow user to leave page otherwise you prevent the navigation and save the data entered by user okay it was some small lecture now let's jump right to the code and see this everything in action okay for those who didn't see the first part i'm going to reuse the project from previous video this is just a super simple application which has two roles home and admin and there inside we have three tabs we can we can navigate there and yeah we have add product at user and some form inside these roads so pretty pretty straightforward this is how it looks in uh source code so we have admin model which contains the add user product so basically everything under this road and we have oops and we have also home which is a very simple component out it is our service or fake out service and we have also authentication guard here and also permission guard so for this um video it is not so relevant this is for previous one what is also worth to mention is this app routing so this is all roads for our application that's the file we're going to work with in this video as well but let's uh go step by step all right what i'm going to do i'm going to add candy activate router guard for add product router and once we try to navigate from add product this card should check if our form is dirty means if we already typed some value inside and if so we should see some dialog window and we're going to use the angular material dialog window with the uh forward cancel button so if we press forward we navigate from this road and if we click cancel we stay on this road or if it wasn't if the form was not touched at all then we just let user go so yeah let's get started and i will put i will create the guard first of all yeah let's start with it and i'm going to create it under the okay let's keep all guards under this house why not and i'm going to use nx console extension or to generate the guard like i'm going to name it form guard then i'm going to say that it should implement can deactivate interface and then i will just skip tests and i click a run button in order to generate the guard for me and this nx console extension will do it and you can see that we have created form a guard guard ts file for whatever reason it created out from us okay let's pull it there and let's have a look how it looks like so as any rotor guard it is just a service which implements can deactivate interface and this is the method which is required to be implemented by this interface and the next thing we have to do we have to attach uh this card to some certain road and as i told that we're going to attach it to add product guard so let's find it in abroad model and we see here's add product and we can say that can i deactivate and provide the array with our guard so as you can see this is array there can be i know some multiple guards if you need it but in this particular case we're going to use the only one and if we save it and let's maybe put some console log here so i'm going to save it and now let's try to navigate from add user let's clean up this one and you can see that it was triggered uh so this is it means that our candy activate was involved yeah before we try to leave this at product road you can see here i'm checking permissions this is from previous video this is another guard but we are not interested in it for now so i'm going to remove this part and you can see that it's so far it's quite useless because it always returns true so user always can leave our guard which makes not too much sense and let's bring some um i know logic to it right and let's have a look at parameters which takes this can activate so we have the current route um or activated road snapshot we have the router state snapshot and we have the next state so this is the snapshot for the router where we end up if we pass this guard okay this is the rotor we go to because maybe your logic can depend on the condition of the rotor you go to and for the reason you have to you know check it somehow i don't know i don't really have example for it but if you know please write in the comments this and the most interesting part is the first parameter and this is the component and so far it is unknown and it makes sense because typescript cannot know in advance to which router we will attach this guard but we know and we attach it to at product so in the first argument for can deactivate method we will get the router which associated with this path right so here we will get add product component and i already hear how more experienced developers say that no we don't need to con depend on concrete uh component led abstracted because dependency inversion and things like that we will do it don't worry but let's give the chance to less experienced developers to understand uh why interfaces or some ups and other abstractions might be beneficial for this use case so but let's continue so far yeah that's this refactoring we will do a bit later at the very end uh but yeah we have the component right and we know that we have some form and basically what we can do is return the component or i don't need this i i can return component form and i can say that if it's dirty we should return false and false means that we are we're not allowed to navigate from this road and true allows to navigate so if our form is dirty we return false otherwise it's true let's check if it works so i go here i type something so i make this form dirty and it will not work because we on the add user so let's switch to add product i type things and now if i try to leave this page you see it doesn't allow me to go to the show list road because this form is dirty all right so let's maybe bring some option for a user uh which allows user to ignore this warning and leave our role so i can say like if component form dirty so if it's dirty right we have to perform another check like if user confirms that he's sure that he wants to leave the page we return true right and otherwise we would return false so here we go yeah and by default we return true right oops true if uh the component if the form was not touched at all we return true so we skip this part in um in that case all right so let's go here i type something and i try to navigate away and you see here we are being asked if we're sure that we want to go and i press ok and i navigated back if i oops this save doesn't work anyway if i navigate back and i say cancel in this case i stay on the same road so this is the very basic implementation but like who uses this confirm this looks ugly right so let's implement it with a proper dialogue like material dialogue so let's get started and i'm going to create another component and it's going to be con firm dialogue and it's gonna be a css display below okay it looks like it's done and under the admin yeah we have confirmed dialogue super simple and let's maybe add some i don't know template like are you sure or let's try to speed it up a little bit so welcome back i added some templates so this is just uh some title you can see my dialogue title thingy and this is my dialect content actions and so this everything basically the angular material layout uh and here's one important thing to mention that this mod dialog close directive it closes the dialog and by default it returns some faulty value but we can define another value we want uh and this value will be returned if user clicks on this forward button so dialog closes and returned very we defined with for this dialog close directive i hope it's clear and you see we have the error here because we have to import uh material material dialog model to our admin model so let's do it here we go now i save it i close this file you can see errors disappeared and now let's go back to our guard and we have to inject our dialogue service which comes from angular materials so i introduced constructor here let's say private dialogue and mod dialog i believe it called like this okay and now instead of uh this confirm are you sure we so we return it and if our form is dirty then we have to create dialogue window right so let's create a constant i will call it dialog ref and we're going to open a new dialog so the first parameter this is the component we have to we want to render in this dialogue so it's a con firm dialogue component and we can provide some i don't know additional dialog config but i will leave it as it is because we don't need it so far then a dialog graph has such a thing called after clause i believe and this is the method which returns observable and here in this stream we get the value which basically dispatch this directive on close event so it emits either some falsy value in that stream if we click cancel or they will be returned true in that stream inside inside this after open because yeah we defined here true so once we click it we return true so it means that we can return uh only this part right and it complains i don't get it ah sorry i typed after open we need after closed yeah here we go so what we have done just uh briefly if form is dirty we create the dialog yeah we wait until user interact with one of this button if we click on some of this button either this or that will be returned value which we defined for this dialog close directive so it will be either something falsey or true value then it goes to this stream and this stream we returns and once we get some value in this stream uh then angular either cancel navigation at all or it will initiate the new navigation which redirects user to the road he initially wanted to go and if um our form is not dirty we return true but let maybe uh keep everything observable i will wrap it into off just for consistency because we work with observables in this case uh those three guys i'm going to remove i save it and now let's try it out so i go to our application just reload it and let's type something now i'm going to leave the page and here we go we see this nice dialog which asks and warn us that we will lose all data we are scared about this i click cancel we stay on this screen and if i as example click forward we should be navigated to add user and as you can see it works perfectly fine now the last thing let's do some refactoring and make it a bit more flexible and i am about this part you can see that we depend on some concrete component that's bad because we don't know where we want to reuse this component or this guard maybe we want to in the future protect not only add product route but we want to add it to add user as example why not so in this case uh our router guard will get not an add product component but at user component if we will try to go away from add user route right and it would not work because this add user component may have different api because there is no any guarantee that the add user has this form property so we have to make it a little bit more flexible and i would suggest you to depend not on the concrete component but on some interface and let's create this interface i'm going to create i will name it oh my god how to name it save data interface sorry guys i'm terrible with naming so but i hope it will not confuse you at all let's export interface call it save data whatever and here we could define that every component or class whatever which implements save that data interface you should have a form like form group or what do we use uh but still this is like we depend on some concrete form but who knows maybe we don't need any form maybe we depend on some internal state whatever so i would suggest you to uh have instead of form property method and this method will be is data saved yeah and it will return boolean here we go and we can remove this in unused import then i'm going to copy this save data i close it and i'm going to implement this for every component which uses which is protected by this form guard and let's have a look where we attach it we attach this to add user and add product so let's go to add product and we implement besides only need we also implement save data and we have to implement interface is data saved and it will return very simple check this form dirty and we have to reverse it like this so if it's not dirty means data is saved and let's copy it and do the same for add user as well so i go to add user and we implement save save data and i place a saved method here below so don't forget to save everything here yes i want to save it and then we go to to to to our guard of this form guard and now instead of this add product component we say that it's going to be something which implements safe data we don't know which exactly component is there but we know that this component has method is data saved and is everything what we have to know or everything what this guard needs to know and now we can save and check our final solution so you remember we added this to end user as well so i try to type something i navigate back and nothing has been changed why because we either ah of course because if uh data saved we don't need the confirmation dialogue we need it when data is not safe yeah so i forgot to reverse it and now if we save it should work fine hopefully so add product i type things then i try to navigate to add user i see dialog window so i can cancel so we stay then i click forward we navigate to add user and if i do the same for the user and try to go show list as example we see again the dialog window and it was working with both this component together so this is how you can make your guard a bit more flexible all right guys that was it i hope you found this video useful and if so please share this video with your colleagues and friends and also don't forget that i have couple of video courses the first one is about graphql engine called hasura which allows you turn your database into real-time graphql endpoints within literally minutes and the second one is about angular material theming those are great courses please check it out the links will be in the video description as well as some coupon codes and i wish you productive week ahead stay safe and see you in two weeks bye
Info
Channel: Decoded Frontend
Views: 3,224
Rating: undefined out of 5
Keywords: candeactivate guard in angular, candeactivate angular, candeactivate route guard, candeactivate in angular, candeactivate guard, candeactivate guard not working, candeactivate angular 9, canactivate angular 10, angular guards tutorial, guards angular 11, candeactivate gaurd in angular, angular router guards, candeactivate gourd in angular, angular 12 tutorial, angular routing, Angular 12
Id: FBFI6scpgHI
Channel Id: undefined
Length: 25min 55sec (1555 seconds)
Published: Tue Jul 06 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.