Lesson Description
The "Functional Route Guards" Lesson is part of the full, Intermediate Angular: Signals & Dependency Injection course featured in this preview video. Here's what you'd learn in this lesson:
Alex adds route protection to the application using guards with the inject function. He demonstrates how to check permissions, like admin status stored in local storage, to allow or deny access to certain paths, and covers different types of guards such as canActivate, canMatch, canDeactivate, and canActivateChild, and mentions lazy loading for performance optimization.
Transcript from the "Functional Route Guards" Lesson
[00:00:00]
>> Alex Okrushko: We have some paths here, like admin, and we want to protect this. We don't want anybody just to get in there, for example, based on permissions or based on authentication, based on many other things. Maybe there's only specific people should be able to create the event. Again, I'm not going to go into all the sophisticated permissions, how to get them, and all this, RBAC and things like that, but I just want to show you how you can protect the path with a guard.
[00:00:37]
So we'll create functional guard. And once again, getting back to this inject function, before that, it wasn't possible. We needed to have class-based guards. With inject function, we can do more functional things, including the guards themselves. So let's create the guard in our core. I'll create the new file. I'll call it auth.guard.
[00:01:09]
Right, and I'll create the guard, so I'm going to export this guard. And the way I'll do it is, I'm going to give this, you know this is a function. I'm not writing it as a function, I'm writing as a const, because I want to provide a specific type for it, just so I'm making sure that this is the right type for it, so I can say that, hey, this is the can activate function.
[00:01:45]
Right, so this is a function. Again, typically we'll have function as functions. In different frameworks, it's very loose, a lot of consts are basically callback functions. Typically, I prefer functions to have like a function name, but again, this is one of those examples where we do want to provide specific type for the function, so that's why we write it as a constant.
[00:02:17]
And then what it will take is it will take our route, and it can also take the router state snapshot. State, and then we'll do certain things with us, so. Beauty of functional approach, we can now inject the router directly here, inject router. All right, we'll inject the router and we'll do a few checks here, so I'm going to do a little cheating here.
[00:02:57]
I'm going to be looking at the local storage to set the flag if I'm admin or not, right? But in reality, this is where you'll have your asynchronous or synchronous permission checking, most likely asynchronous, which probably already cached on your app anyway. So we'll just check if it's admin, is admin. Admin, and we'll read the local storage.
[00:03:34]
We'll just get the item for is it admin or not, and if it's equal equal to true. Then it's admin. I notice again, I'm not comparing to boolean value, I'm comparing to a string because anything was stored in a local storage is basically a string or an object, right? It's not really boolean. Admin is misspelled, there you go.
[00:04:03]
Okay, so now, if it's admin, if it's is admin, then we'll just return, return true and we're done. So guard, we need to return either boolean, true or false, or we need to return a new URL tree, which is basically where to redirect, so which we need to create. All right, so I don't really need the else case because I'm basically returning out of the function already.
[00:04:38]
You can't have else case, but we can do just some alerting. This is just the built-in dumb stuff. You can say, hey, whatever, no access here. Something like that. And then we'll return, that's why we were injecting router. We need to return and your URL tree, and router create URL tree helps us create one. And in this case, we just say, hey, it's just a homepage, so go there.
[00:05:15]
But if you wanted to have some login page or something like that, this is what you'll create this. If you are, for example, protecting the authentication and not authenticated users. All right, so now we have this guard. Let's use it. So in our routes config, this create will also be protected by this guard and for activation, meaning getting there, you can have activate, can activate, and we can have this auth guard.
[00:06:02]
Notice it's an array, it's an array because you can have multiple guards depending on different things. One is just pure authentication, the other one is like the specific permission for this authenticated user, so you can provide them all and they'll basically pass each other and check if you can get there or not.
[00:06:39]
All right, can activate. Perfect. So let's make sure that I don't have it, because I probably do. Yes, I have my admin, let me just, I said this to false. False. Right, so now in my app, if I'm here and I'm trying to get to admin. No access here, right? So it basically the guard kicked in and it stops me from getting here.
[00:07:20]
Now, let's make sure that we can get there if I change it to true. Right. I'm through. So there are a few other things here that Angular provides. Can activate is one of them. There's also can match. So it's also like more advanced can activate. It can do deeper analysis and analyze what exactly needs to be done. And by default in your route can match, it can also use the can deactivate.
[00:07:57]
Meaning when you're trying to leave the page to something else, never you're navigating getting away, can you navigate away, and this is maybe where you want to check that, hey, did you save the data or something like that from the forms, things like that. So those are other advanced things. There's also can load.
[00:08:24]
Right now, it says it's deprecated, you can't match. Okay, so that's what it is, can match, you can match, so this is deprecated, there you go, you've seen that here. Can load typically won't even load the JavaScript for that route if it's not, but can match looks like you can do that and more. So those are some of this, and then also can activate child, a path can have some children.
[00:09:02]
So it's a way to group different paths together. So the children can activate child is also basically make sure that any of the children are protected by the same guard as well. One more thing while we're at the routing. Right now, we have a component that is loaded, basically eagerly. We can do different things here as well.
[00:09:44]
We can do the lazy loading here, so we can have load, load children, which is multiple paths, or we can load the specific component. This is a way to lazy load and split this to a whole new from a different chunk, so right now we can see the chunks. They're all together, so if we can load this component lazily, so I'll do the import path here.
[00:10:22]
Import, and this component comes from this feature create event. So we load that, and then this will load the module and then the module, basically the entire file, and then this is the create event. Let's see. Right away, boom, we can see here. We now have the initial chunks, let me see if you can see, we have initial chunks and then we have a lazy chunk files, so you can see it different, right?
[00:11:07]
So now this create event is lazy loaded. This is one of the performance optimization techniques in general, but since we're discussing the routing and path, I just decided to show you here as well. Very powerful thing. Right, very powerful thing. Yes, and you can specify again, additional providers here as well for the specific path.
[00:11:37]
And very powerful, lot of interesting things here. This is probably a lot of times you would use it in the any application. You'll probably use this lazy loading and can activate because most likely your apps have different permissions, different levels. All right, there's a question about with component input binding.
[00:12:04]
Can you overwrite the value, for example, in the event detail component? You passed an input called ID that was a value that came from some other component, which value would win? If I think they're asking if another ID in scope. Yeah, so the cool, interesting part here is that our event details page is not part of any other parent page.
[00:12:36]
So we're not using the event details as a child of any other component. It's navigated through the routing, so when we navigate through the routing, the only way to get here is through this ID. If you choose to have this event details page as the child of some component, then with input binding, basically it doesn't work because you're not routing to it, and then your parent component would have to specify this ID.
Learn Straight from the Experts Who Shape the Modern Web
- 250+In-depth Courses
- Industry Leading Experts
- 24Learning Paths
- Live Interactive Workshops