Angular Router - The Basics and Beyond

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] the router is one of the most powerful yet underutilized tools and angular in addition to defining the URL structure for your app it can also be used to control performance with lazy loading and help you write dry code with resolvers and guards over the next few minutes you'll learn the basics of the angular 6 router plus a few advanced techniques to preload data from firebase and protect routes from unauthenticated users if you're new here like and subscribe and grab the full write-up from angular firebase com the first thing we'll do to get started is generate a brand new angular 6 app with the router flag that'll just give us a routing module automatically the first thing we'll want to look at is the router outlet when you route to a component it needs to be the child of some other component which by default will be the app component and the root of the project so the outlet tells angular where to render a component based on the URL that the user navigates to we can define our routes by going into the app routing module and you'll see we have an array that's typed to the routes interface we can define each route in our application as an object which will take a couple of configuration parameters the most basic use case would be to give your route up path and then route it to a specific component that you've generated let's run ng generate component and we'll call this the home page now the home page we could set up as the root path so we'll give that a path property of an empty string then set the component option to the home component if we serve the app we should see the home component rendered at the position of that router outlet then notice how other content in the home component is still there such as the logo and header that'd be a good place to put a nav bar at a footer and things that'll be present on every page that's a good start but let's look at how we can navigate between multiple components by generating another one called animals then we can import the component into our router module and set up another path and component property for this route when setting up hyperlinks in angular you don't use a normal H rep attribute like you would in a plain HTML page if you use a regular href that'll cause your angular app to completely reload whenever it's clicked instead we use the router link directive which tells angular to treat this as an internal route then we simply pass it the path that we would normally route to you with a link so now if we open up the app in the browser we can click on this animals link and it will route us to the corresponding component so that takes care of your most basic use case but what happens in the real world is generally you're pulling some information from a database then route to a specific ID to show more information about that item and you might have thousands or millions of items in your database so you can't just hard code all of those routes manually in this next section we'll create a component called animal detail and we're going to make it a child route of animals you can create child routes that will be rendered inside of their parent by adding the children property to the parent route the children property itself will take an array of routes so we just have a classic tree structure here we can define a dynamic URL parameter by putting a colon in front of whatever that parameter is in this case we're going to be looking up animals by their name in our database so we'll set up colon name as that URL parameter doing this means that we can navigate to routes that will look like animal slash elephant animal slash hard work or any other dynamic property that we pass to the second half of that URL segment you'll notice that we're dynamically generating a list of links that we're pulling from firebase so let me show you how I do that in the parent component I have an array of documents that I pulled from fire store so I can loop over them asynchronously with ng4 and the async pipe then to build a link instead of passing it a string I'll put brackets around the router links so we can pass it an expression which in this case will be an array where each item in that array represents a URL segment so the first half of the segment is animals and the second half will be the animals name because this is a parent component we'll need to tell the router where to render that child components which we can do with a router outlet the actual data in the database is just a collection of animals that have a few properties on each document inside the parent component we can retrieve these documents with pretty much just a single line of code we inject firestore in the constructor and then reference these documents as the animals property and call value changes to listen to them as a real-time observable and the child the component things are a little more tricky because we need to also listen to the change in the URL parameter to get the proper animal from the database the angular router provides a service called activated route that allows us to listen to state changes in the router and then we'll also import the switch map operator from rxjs the important thing to understand here is that the component is only initialized once when the first route is navigated to any child routes that are navigated to after that won't be called with ng on a net so what we want to do here is use activated route to listen to changes in that URL parameter which is the animals name which we can do by calling route per a map which returns an observable of the route parameters then when a change occurs we'll call switch map to switch to an observable of the actual animal data from buyer store notice how we're calling params get name which matches the dynamic URL segment that we said and the router config so that returns the actual name of the animal which we can then pass on to fire store to retrieve as a single document the last step is just to unwrap this document in the child component so we can do that with ng if animal async then set that as a template variable of animal and we'll just show some of the properties here in the components such as the name bio and image and you know have a structured router tree that will scale up to as many documents as you have saved in the database up until this point we've only been using router links to navigate but you can also navigate directly from inside of the components type script there are many cases where you just can't use a link click to navigate to a page and you want to do it in a more dynamic way maybe you have some really ugly animals in your database and you want to prompt the user to say yes before navigating in this case we will import the router directly into our component will set up a click handler here that will first prompt the user to confirm that they want to navigate to this page and then if they type in yes we'll go ahead and navigate to that page manually with the router you can say router navigate and have it go to the array of URL segments that you point it to back in the HTML we can go ahead and remove the router link and replace it with the click event that will run our click handler whenever it's clicked so the key takeaway here is that you can navigate anywhere in your angular code outside of the scope of a regular hyperlink now I want to go ahead and switch gears and show you a couple things that are just super useful to do with the router let's say you want to create a catch-all route that will serve more or less as a 404 page if the user routes to a component that doesn't exist we can generate a new component to show the content and then we'll say path star star as a wild-card and you want to make sure that this route is the very last route in your treaty then if we go and type in some random URL into the browser it's going to pull up our error component instead of just throwing a regular error to the end user then another very common thing you might want to do is instead of routing to a component you might just want to redirect to a different route so let's say we have a common misspelling for animals we can just redirect to the main animal's route when you set up a redirect route you'll have to also add in the path match option otherwise angular will throw an error if we go and navigate to this route in the browser you'll see it redirects us to the animals component instead of bringing up the error component that we just created another cool thing you can do is use the router link active directive to provide a CSS class whenever a certain route is active this makes it really easy to build out UI features that show the user which link they're currently on it expects a list of CSS classes on the right-hand side so we'll define an active CSS class that will make the font bold and a different color now you can see we get a clear UI change every time we go to a different link for the next few minutes I want to move a little beyond the basics and talk about guards to protect routes create reusable code and preload data into your components a guard is just an angular service that has some special interfaces that we can implement to do things with the router one of the most common use cases is to protect routes from unauthorized users let's go ahead and run ng generate guard admin that will protect our routes from any non admin users the special interface we'll be using here is can activate which will only activate this route if that guard results to true let's go ahead and lock down our animals route by adding the can activate property with the admin guard if we go into the guard itself you'll see it it is decorated with injectable just like any other angular service the only special thing is that has this can activate interface that gives us some information about the state at the route in order for the guard to work we just need to return a boolean which can be a primitive work being observable or promised it's an observable it's going to automatically subscribe for you so we'll go ahead and send an alert that says only admins allowed and then we'll return false to block access to this route if we try to navigate to the animals page you can see we get this alert and the component is never rendered but more often than not you'll need to do this a synchronously by checking with some API if this user has authorization we can simulate this by setting up a timer of 1000 milliseconds then we'll need to map the emitted value down to a boolean then we can also use the tap operator to show an alert or this is a good place to navigate to a login page or something along those lines if we try to navigate to the page at this time you'll see we get a one-second delay and then it finally blocks the route after this observable is resolved can activate is a very powerful interface at your disposal but there's also another one called resolve that can preload data into your route do you remember earlier how in the animal detail component we listen to the name parameter and then switch map to a different observable well maybe there's a better way we can do this imagine we wanted to preload this data on multiple different components we would have to write this code for each one of them instead of repeating ourselves let's generate a guard called preload instead of using they can activate interface will use the resolve interface and you could strong type this as well but for now we'll just use any then we'll change the method name to resolve and it's pretty similar to can't activate but instead will return the actual data that we want to be available when this route is navigated to and commonly that's going to be an observable form because you're probably pulling this data from some external API in our case we'll do it with angular firestorm so we can inject that in the constructor then the guard will have the actual parameter name available as a plain object which we can retrieve with next parameter in the data as an observable but we have to pipe in the first operator because firebase returns real time stream and we need this observable to complete in order for it to work properly now we can just comment out all of our previous code and instead we'll just define the animal as the data that is now available on this route when it's navigated to it's now available on the route data property and then we can apply it to this route by going back to our router config then add the result property to our preload guard if we open up the app it's going to work in exactly the same way as it did before but now we've isolated this code in a reusable way that we can apply to multiple routes as needed hopefully that gives you a basic idea about how powerful the angular router can be I'm gonna go ahead and wrap things up there if this video helped you please like and subscribe and if you really want to master the basics of angular consider becoming a pro member at angular firebase comm you'll get access to a whole bunch of exclusive content designed to help you build and ship your app faster thanks for watching and I'll talk to you soon
Info
Channel: Fireship
Views: 77,443
Rating: 4.9129596 out of 5
Keywords: angular, angular 2, firebase, webdev, app development, typescript, javascript, angular 6, firestore, angular router, angular6 router, angular router tutorial, router guards, route guard, angular routes, router tutorial
Id: Np3ULAMqwNo
Channel Id: undefined
Length: 11min 47sec (707 seconds)
Published: Tue Jun 12 2018
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.