Ionic 5 App Navigation with Login, Guards & Tabs Area

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] what's up simonix welcome back to a new tutorial and this one's going to be a bit longer i guess because i wanted to give you an example an overview about how to structure a very common use case of an application which means showing an introduction page showing a login page potentially also a sign up and then moving into a tab area which could also be just a site menu area or anything else but just this whole example of the user flow for applications that require login and a great startup so let's dive into this um there are a few things and actually a lot of code in this full navigation template whatever you want to call it so grab the code also below the video link to the full tutorial on devtektek if you want to follow along perhaps that's a great idea so what you can do to start your application is just start an application based on the tips template because i actually found that by now the setup is fine so we will use this and we can easily change this to have a login and introduction page before this what we need as well is a little service which will hold our authentication state and also make hdp requests to a little dummy api and of course we need two additional pages for the introduction and login the inside area will stay just like it is and then things get interesting because we're going to generate three guards the first one will protect our inside area the second one will show the introduction page automatically and the third one will automatically lock in users once they are locked in in all of them uh implement directly the right interface you can specify this on the command line as well so dash implements can load uh in the past we always use can activate but i learned that can load is actually better connective means it's a check if a route can be activated and in the background actually the module will be loaded so you can see this from the network tab of your browser if you use the can load guard instead the check will run and if the result is false the whole module of the page you want to access isn't even loaded so that's actually a better way since all our pages are modules with ionic lazy loaded modules and that works great so we got a blank ionic tab application right here maybe i could do this to the side so we always see the difference um i will experiment with this a bit first of all let's go to our app module and add the http client module because we're going to make an http request and that's what we need so edit to the imports of your page now we can move on to the app routing which is now um well with the two new pages and the empty pages going to the tabs so we want to change this a bit first of all let's say we start on the login page and therefore i will add a little redirect isn't this usually always in here strange but we want to make the empty pad redirect to log in and for the tabs we instead also want to use tabs um we can keep the introduction page in here that's just fine and now we will also apply our guards directly actually no not can load it should be in like this um hello okay great um so the login page can usually load all the time but if we haven't seen the introduction uh we want to show the introduction screen before so we will keep it kind of out of the routing but automatically display it if the user hasn't seen it and we can use our introduction guard for this it's really a great way also in a mobile application imagine on the user logged in is using the application and somehow kills the application if the user is now restarting the app he or she would be back on the login screen so what we can do now is add another guard which is our auto login guard to the login page which will check if the user is already authenticated and directly bring him or her back into the application and you can use multiple guards in can load no problem so taps holds all the information of the inside area in our case and therefore we want to protect it using our authentication guard just like this all the guards right now that we generated simply return true so we don't have any problems or we can easily work with them like it is now and once we reload the application um we are now finally on a login page but before the login we actually want to see the introduction so let's move into our introduction guard and i will remove a bit so it becomes actually more clear we want to return an observable i think that's right and we also need to inject private router here in the constructor there we go all right um can load should now check if we have seen the introduction um therefore we will use the um can we just get rid of all of this we will use the capacitor storage uh because um i just wanted to use capacitor and we've used ionic native way too often already in the past so let's simply import plugins and destructure it to use the storage engine which works a bit different um because it's real not really storing objects but only strings um but anyway we can still check has seen intro equals awaits storage get and then the notation is a bit different you put it like this you want to check for a specific key and i define this as a const here because we will use this in other places and we don't want to use the string in different places so just make stuff like this a const export it and then import it in the right places because we use weight we're going to have to use as ink in here and actually i just noticed that it's a promise not an observable so this will give us back a value and this value has seen intro um actually has another key inside called value which is the real value and as i said in the storage we will only store strings so normally this would be just a boolean but in our case we really need to check for true i feel kind of dumb for doing this but um that's just how ionic storage works you can still uh string if i json objects so json stringify works totally fine but we will store the string true which is still fine so if the user has already seen the introduction and wants to navigate to login we should return true because it should be allowed in the other case we want to return true because the user shouldn't directly navigate to the login but instead we will use our very own router navigate by url and we want to navigate to slash introduction yeah and make sure you put the brackets in the right places now the problem with this approach is um in some places or we will use this in other places of the app as well that on an android device you can easily go back for example you log in you're inside you press back your backup login and you don't really want this in the past you could use the navigation controller which you can still use with ionic to set the root application on or the root page and you can basically achieve the same result by saying replace your el true for any navigation that you use this will just reset um the navigation stack and replace the whole url so now if we try and open or refresh the login page we should actually be well looks like i already got that uh key so let me quickly remove this if you're interested in this you can actually find it within local storage and capacitor intro scene so that's added by capacitor i will just uh delete this one i think this is error all from other let's just can we just remove everything anyway let's keep it like this and now we're finally on the introduction page because our authentication guard um took over it has seen that we haven't seen the intro so the introduction is shown great we got that logic in place so let's move on to the introduction page and i think if i'm going at this pace uh it will be like an hour video so i'll bring in some code uh once again check out link below the video so you can easily follow along in a bit better way for our introduction page we want to implement two functions we want to have a function to go to a next slide because sometimes you want to have buttons on that page to manually control an ionic slide which is a great um no ion slides actually which is a great component for an introduction page you see this in all places so let's call this one slides and it's of the type ion slides come on ion slides not slide and with that view child in place we will access the view child in the html and we can call slides next once we finish it we will start click the start button and we are going to set once again the value which we now have to import from our page um from the introduction guard but that's what i wanted to say you could now also have has seen or whatever the name was in this place but it's a lot easier to use a constant for keys like this so import plugins and storage plugins once again and then we can set that key and then route forward uh let's inject the private router once again router and then we can navigate to the login and replace everything so that's our logic in here and for the content we will simply use ion slides um i will bring this in because i just wanted to use two images um from the ionic academy as a quick example let's try and refresh maybe we should also save this um right now this doesn't actually look too good so you really need to tweak the slides a bit we do have slides it looks okay but the button here is above our elements so we want to make this cover the whole page and we're going to give it a little background color and you can do all of this from css in fact um we can overwrite the background color of ion content for example we could change the bullet background colors of the ion slides which is this little ball and we can also change the height of the view which then becomes a view that looks a lot cooler oh we got everything centered on the page that's fine we can also press next to go next so this is now our introduction and you see if the user would open the application there's no flash of the login page because we got that guard which isn't even showing the login page so that's really a great way to prevent pages from even being displayed for just a short amount of time all right so great login a great introduction and on start we should hopefully get to our login page and now we have set the key we can refresh the page and the user wouldn't see the introduction again so we're finished with the introduction and we can move on to the actual login for this we need to take a little step back and move to our service that we generated because within that service um we also need a few things first of all we will also need access to the storage and we will also set another token key because i just recommend it all the time then we will have two members here we will have an is authenticated behavior subject behavior subject is a bit different from subject because it has an initial value and we will set this initial value to null for a very specific reason that we will see later and i will explain why and also you could store your json web token locally in the servers you can write it to storage you could do basically whatever you want so then let's inject the http client as usual and we will create a few functions um we will load the token once the application starts so let's call load token in here we want to allow a login and of course we also want a lock out function and i will bring in the code um because that will make life a bit easier so we're going to use a simple mock api called request dot in i have really no idea where i found this and it gives a nice successful or unsuccessful login and that's what i really wanted for this tutorial so therefore within the login we will make a post request to the api route using the credentials and actually the credentials for that api should be email and password um so let's say the type is email and password more like this i would say and it will return an observable of the type any all right with the result we want to add a little pipe block because if you check out the result is token whatever so we can map the data and extract the token from that object maybe we should add a few more operators from rxjs like map tab and switch map and then things get a bit more difficult our map is just a plane mapping of data switch map means you switch from the original observable to a new observable as you can see we return a new observable because we want to set the data to the capacitor storage and this call here this set call returns a promise which is a bit difficult in the context of observables but with from we can actually transform a promise to an observable which means in the end we return a full new observable and the inside area here was a promise but we transformed it with from now we just need to import from from from from somewhere i think where are my imports this is really messed up here so from from rxjs all right that means uh in the end we have a different observable but we can be sure that the first request is finished and that we've written the data to the storage um then we will call our behavior subject and emit a new value with next and that's the same we will do in the log out but here we will emit faults so people or we from code can subscribe to the behavior subject from everywhere in our application and with next we would always get a new value and we can use this in our guards later on which will really help our application okay um that also means that after a successful login we have stored a token so we can also load that token in the beginning remember this could be adjacent web token to your real api so once the application starts we can once again get from the storage our token it's a promise so we need to await the result the result is once again in token.value and we will actually add a little lock to lock it out then you could store it locally um you can attach it to all further requests to your api i got other tutorials about that as well just check them out on my channel and of course we can also set the authentication state to choose since we got the token you might want to add a little check if the token is still valid but that's kind of easy for a json web token and now finally on the lockout we will just remove this token from storage once again and you see this const really uh was a great idea because we used it in a lot of places and you would have just an arbitrary string in all these places which doesn't really look too good so um this one actually now returns a promise i just want to add this um so you're not confused about the usage of maybe a function that returns a promise or an observable really clean service so far and we're already at 17 minutes but we're on a good way i would say so let's move on to our uh login page okay it's in pages um login page login login module is the first one we go to because we need the reactive forms module we'll actually make a kind of nice uh form with error messages as well um yeah maybe i should edit here and therefore we need to add the reactive forms module now we can go to the login page and i will bring in a bit of stuff for the constructor so we got all of that in place can we just add all missing imports yeah yeah it's never really working um i don't know what's the path to up okay great with the form builder we can now construct our form and we will just create it up here credentials will be a form group and within our initialize we can now create it these credentials are actually the ones that will return a successful token if you change anything in the field it won't be a successful request so because i couldn't really remember them i just put them in here usually you wouldn't have them in here the first one required an email second one required admin link we will see why this is important in our view later on because we can have specific error messages for these errors but to access them a bit easily or more easily you should make them easily available that was a bit easily too often with a little getter so to get the email we will return the form element and here as well or the form control actually to put it right so finally we also need a login function and within the login function we just need to make the request through our service and handle the result success means we got a token everything's fine and we can route forward error case means well we should display an error and that's what we can do with the following code so we can first of all present a loading uh which is a great idea because api calls might take like a few seconds depending on your connection and for all of this make sure you put a weight in here i've seen examples where we haven't added a weight here and the uh the api returned really quickly and then you're trying to dismiss loading once you're done which wasn't even presented which can lead to a lot of problems so really make sure you always await until the promises are finished and then we can send the value of our form group to the login service and on the successful login we just dismiss the loading and navigate to tabs once again replace the url in the error case we can simply dismiss the loading and show an error and as you can see even if we are using um as a weight in these blocks which usually just look like this for http calls you can always just add the as in keyword in front of it to mark it as as in so that okay that's and there we go and with all of this in place let's move to the login page i will just implement the login because i'm pretty sure that you're able to implement the sign up after this just generate a new page and add the routing and then move to that page and build it accordingly to the login page but the login page is the first and most important noun so we will start with a form um form group is our credentials form and on submit we want to call the login function great now we will use a simple ion items i'd say and ion input first one should have the type email this will change the keyboard on a silence on a mobile device i will not add any labels for this i will just use a placeholder in this case and the form control name is email great same for the second one which is type text so we don't really need it placeholder would be password actually the type is password so the characters are hidden yeah placeholder always great and then copy this and copy that now we got the input fields in place and we need a button to submit our form to submit it just use the type submit if you want to have other buttons on this page you should use the type button because every button that has no type or the type submit will trigger the form if they're within the form and of course we only want this with one button but the other button might for example um show you a message like not yet a member sign up and for that you of course don't want to trigger the submit action but for the real uh submit button we can now make it a block and put it on the disabled state until our credentials form is valid as a quick example i will also add two more buttons for example sign in with google or sign in with apple which will now give us a view like this actually a nice basic view but we can even improve this a bit more so all of these things won't have any action only the login but we are not yet finished with that view so i wanted to put a little background image on that page because i think that's a quite common case to have a background image on your login page and we can do this by using ion content this first is just a bit about padding and the background is setting the background image you can use your l2 local file i just use an image from unsplash because i was kind of lazy and edit this to make it fit the screen it's not perfect but it will show actually quite nice you see it looks better we got a bit of padding more padding to the top we got padding on the sides we got the background image and the buttons now look a lot better now what i also wanted to do is show specific errors for these error input fields i think that's also a very common case and we usually left this stuff out so for each of our items i will create another div and this is a bit tricky so i will bring it in because i'm way too lazy first of all we only want to display this div if the email control was dirty or touched which means the user put the cursor into it and navigated away or somehow changed it so only in that case we want to display any kind of errors and also only if we actually got arrows and once you're at that place you can check for very specific errors so for example required or email if one of these is available inside the errors object you can display the according error for that case same for password um once again kind of same logic but this time using the password control and also checking password errors exists and then using either required or min length to display different error messages so out of the box once again this won't really look cool let's you see the email is gone the error is actually below the field so there we go password needs to be six characters and email is invalid but we can do a bit more to style this so for all the arrows we will use a small font size a color making the background a bit of red and using a bit of padding which results in errors that will now look like this or that and i also wanted to apply a round border to this because all buttons have round borders so therefore i put everything uh from the ion items into a diff class yeah i'm from germany you know it already um into an input group um and let's format everything so there we go everything's inside an input group and that input group will get a bit of background color and border radius and we marked this overflow fault because otherwise the items would actually go above this can we check it out so if i would disable overflow you see the borders of the ion items are like this so by saying overflow hidden we can manage to make it look like this and now we got nice error messages on that page to the user once the fields are touched um or yeah password is required email is required and there we go nice form validation super quick and easy all right we're actually close to um well close to the goal of this example let's try our login um on a successful login yeah i don't know why but i usually get this error whenever i add a function to a servers lately um really no idea why but we can already um add a bit more code while this loads inside the tab one page um we just want to have a quick log out we have added the function to the service already so we can simply um add our authentication service and the router make sure you await the promise so really all the tokens from storage are gone and then navigate back to slash or slash login would be kinda the same in our case now back to the login um let's quickly also go to the tab one html and add our button i will get rid of these things for now uh whatever so ion button lockout now the fun begins of securing our application um you already see we've loaded the token we have no automatic login um we can now really look cannot match any routes tab step one oh yeah i made a mistake oh a terrible mistake inside the tabs routing um we need to also change a bit because um we have added tabs already to our app routing so right here that means if we navigate to slash tabs we will get to the tabs page or the tabs routing module but at this place the first part of the url is already resolved which means we are basically left with the empty path in here and if we start with tabs in here we couldn't match any other pad so therefore we can actually remove this because we will anyway get into the children there is no match for an empty path in here but at the end we have redirect two tabs tab one and that should be fine so that means now we can log in and we are here tabs tab one tab step two the interesting thing is we can directly navigate to them works fine as well the problem is that we can log out and we can navigate there and we're back inside because the area is not yet protected in any kind of way we still need to apply our authentication guard now which is a bit more tricky so let's go to the guards and the authentication guard once again we can get rid of a few things and now we will inject our authentication service and the router can we get all missing imports once again oh nice it's actually the right import so the fun begins we want to check the user enters this page and we need to check or we need to load the token if the token exists and then check if the user is authenticated and then allow access or download and we do this by using our authentication service our service dot is authenticated and pipe the result now um i will leave out a few things first of all to make or to show you why it's not working um so map is authenticated can we just add the damn map is authenticated we'll check if the user is authenticated in that case we can allow access to any page and otherwise we will navigate back to the login and return false now uh let's also log out guard is authenticated come on there we go so let's try and access an inside page um what was it it was like tab step one um guard null now this is an interesting result because null means we actually get the very first value of the behavior subject it should be true or false but not null and that's what i wanted to say in the beginning we used this specific value null here so within this pipe block we can actually filter out the null value so the value should really be unequal to null and otherwise we will filter out that value if we now try it once again um we see guard faults that's fine if the result is false we shouldn't be allowed um but i'm actually not sure did we press lockout yeah i think we kinda did let's try to log in we see guard true we see no login and that is the second problem i wanted to show you i can also do it like this now the page isn't really displayed although the guard is actually true so i was really worried so we have true it returns true why isn't the page coming up the problem in these cases is usually that the observable you return isn't completed and the guard will only display the page if the observable is completed and to do so we add another block here take one which means we will only take one result uh we filter out the null so that's fine and then we will just take true or false one time and then the guard should be finished and as a result we're now able to get directly to tabs tab 1 on the login page we're able to log in and move into our app we are able to refresh we're able to log out and let's see we're not able to see the inside area anymore and it is completely secured because we use the can load guard so the module of the page isn't loading the po the code is never available here within the network tab so that's really a nice security now this is our authentication card and the only thing that's missing is once we've logged in uh and you imagine the user closes the application starts the application again and is back on the login screen that's not really a great idea because we should automatically log in the user and we will do this within our automatic login guard this card is actually mostly the same like our other guard only that we will do things a bit different so the first part is basically the same just like before uh let's import a few things and add all missing imports and remove everything that we don't use and then return whatever can we just silence this okay so i think i feel like we're missing a little bracket we're doing the same on the uh authenticated behavior subject we filter out the value we had take one because we learned from the past and now we map the result but now we want to map if the user is authenticated we want to forward him directly or her to the inside area and otherwise return fall so it's kind of like just the opposite and therefore the code is just if the user is authenticated directly navigate to the tabs area if the user is not authenticated return true which is kind of strange but this just means okay you can access the login page so we're very very generous and you see we were authenticated and we immediately brought back here that means once again no flash of pages that you don't want to see which is really a great feature of our um guards and now log out nothing happens log in we're locked in trying to access the login page automatically forwarded and that's it for our ioniq 5 capacitor full app navigation template example i hope you really enjoyed this video if you want to see more and dive more into ionic check out my ionic academy as usual and otherwise if you get any other questions about templates like these that you would like to see so really um helping you to get started with ionic in a better and faster way let me know in the comments and i wish you a lot of success with the starting point to your application if you enjoyed this video please hit the like button and stay subscribed so you get notified about all the new tutorials quick wins and other app development and web development videos on this channel if you want to learn more about ionic with in-depth courses a community of like-minded developers so you can learn and build your apps faster you should definitely check out the ioniq academy which is my code school to help you with everything ionic with a huge library of courses material and a supportive slack channel so we can get your app out i hope you enjoyed this video i will see you inside the next video have a great day and happy coding silent
Info
Channel: Simon Grimm
Views: 20,885
Rating: undefined out of 5
Keywords: ionic framework, learn ionic, angular, ionic angular, ionic guide, cross platform, hybrid app, ionic for beginners, ionic course, ionic, cordova, javascript, ionic 5, learn ionic 5, ionic 5 for beginners, angular 9, ionic 5 tutorial, ionic 5 angular, ionic 5 course, ionic academy, ionic tutorial
Id: RuuOdfz9Kxc
Channel Id: undefined
Length: 35min 54sec (2154 seconds)
Published: Tue Sep 22 2020
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.