Check out a free preview of the full Angular 13 Fundamentals course:
The "Modules & Routes" Lesson is part of the full, Angular 13 Fundamentals course featured in this preview video. Here's what you'd learn in this lesson:

Lukas discusses the use of modules for the division or grouping of pieces of an application using ES6 modules at a language level and NgModules at a framework level. The use of routes allows for loading components and navigation between modules. Students' questions regarding why modules need to be imported twice and what type of route would be lazy-loaded are also covered in this segment.

Get Unlimited Access Now

Transcript from the "Modules & Routes" Lesson

>> The first thing that we're gonna talk about is modules. Now, modules is a slightly over loaded term in the context of Angular, because what am I talking about when I say module? Well, you have two flavors of a module within Angular. And they do slightly different things.

[00:00:20] So at a language level, we're talking about ES6 modules. And so we use this to provide organization at the language level. And all this does is provides a container for us to export one thing so that we can import it in to another. So In this case, you can see here that we are importing component on a knit, as well as like an item service in an item.

[00:00:47] So this is a way for us to kind of package things up. At a language level, so when it's compiled, it's available it knows where to find it and then make that available. So you can see here We're importing ,essentially ES6 modules that have been exported for consumption.

[00:01:05] Now when I say module, I could be talking about Ngmodule and this provides organization at a framework level. And so this allows us to tell Angular how to configure itself so that it knows what exists and how it needs to fit together. And so, we use declarations to define anything that basically the user is going to see.

[00:01:33] So if you have a component, you declare that. Import, so if you need to import another Ngmodule providers. If you need to export something to make it available, as well as in your top level module, you have a bootstrap property that you define the top level component that's going to be Bootstrap.

[00:01:53] So what this looks like is essentially an object that just has, I think of it as a manifest that here's what we want to import. So these are the modules we're importing. Here's the components that we're declaring. Here's the providers that we want to consume. And then we're going to bootstrap on the app component.

[00:02:19] And then from here, at the very highest level when we're spinning this up. Then we're telling Angular to go ahead and bootstrap the app module. And so Angular is organized in this hierarchical kind of tree shaped component hierarchy in that you have like your top, like your root module which is the entry point and then everything else kind of sits under that.

[00:02:47] And what this allows us to do and I'm getting a little ahead of myself but I can't help myself is that by having this tree shaped hierarchy, is that it works really well for unidirectional data flow that you can have something defined at the top. And then it just kind of flows down the tree and then if something happens, that event is then propagated back up the tree.

[00:03:08] So we can think of modules is really nothing more than a logical grouping or a division mechanism to divide and segment pieces of our application. So I currently am in the Phoenix metro area. And when I picked up John from the airport yesterday, we drove through approximately I want to say 5 or 6 kind of towns that exist within Phoenix Metro.

[00:03:36] So I think of, when you look at a typology of, let's say Phoenix or even Minneapolis or these Metro areas, metropolitan areas is that they are segmented into these smaller kind of independent towns that are all connected. And so if those are modules, then routes would be essentially the streets or the highways, the byways, and so on.

[00:04:06] That allows us to move or navigate from one module to the other. And this is in its simplest form, you're simply defining a path for the URL that is then. Once that pattern has been or that path has been matched via pattern matching then it pulls in and says I'm going to load this component as a result of that.

[00:04:28] So if I go to a courses route, then we can define the courses component that gets loaded into the router outlet. So they're loaded into a router-outlet. And then we have a very convenient mechanism called routerLink that we can use then to navigate to other routes. This is something I don't think about a lot, but it is, especially with single page applications.

[00:04:54] It's relevant that the router uses history.pushState, which means that when you generate an application, there's a base-ref tag in the index.html that says like this is the route. And typically, I don't touch it. It's just there it works. But this allows you to essentially use like the back button, in the forward button and navigate between the routes, which at one point, believe it or not was a problem with single page applications is that you are not actually leaving a page.

[00:05:25] And so how do we actually create kind of canonical URLs to link into certain parts of it? Where I've used this, is I have had an Angular application that was hosted at a sub-directory that was not the root of the domain. And so we had to go in and just update that to say hey, we're not at four slash route.

[00:05:50] We're actually in this directory over here as not to kind of mess everything up. And so this is what a routing table looks like. It's just an array of Route objects, or a. Yep. So it's an array of Route objects that has a path and a component. And there's a few other things you can do in here, is one can activate.

[00:06:17] So let's say you want to protect certain certain routes is that you can use can activate that will call a guard, which we'll look at later, that based on some kind of predetermined logic that will just say true or false. No, can you stay can you go. If you go there'll be trouble.

[00:06:38] But if you stay there's gonna be double. And so you can essentially guard your routes using a simple function that returns true or false. If true, you can go if false met your route. Or the other thing you can do is lazy load a module. And so you can say I wanna go to this route, but I'm going to load in a module that then contains components and we're going to do it that way.

[00:07:05] So this what this does is it reduces kind of the initial load to where you might load one module up front and then individual modules as you navigate through the application. And then last but not least, you'll see that we have a wildcard here at the bottom. And that's just it's a path.

[00:07:21] It's the double Asterix. So it's saying if we match these are nothing matches. Go ahead and just redirect this back to home. Now, this is a pro tip. I don't have this in the slides, but I have been bit by this and so even if I'm in a hurry sometimes I will mess this up.

[00:07:44] But, the routing table is evaluated from top to bottom. And so there's a reason why you want your wildcard at the bottom and not at the top. So I've had it where I've had a very general route in front of a very specific route. And I'm like, why can't I navigate to this thing was because I was firing a route previous to that.

[00:08:06] So the order that you declare your routes in the routing table or that array does matter. And so it's as simple as like, okay, I just need to move this up. And so if you're trying to navigate to like a sub route with like a parameter, that is something to just keep in mind.

[00:08:29] And you can see here that, we're just using routerLink to link to link.path, whatever that is on this object. And there's even a trigger to say, are we on this active link and if it is, and so it's just detecting like what route are we on? And if it's active attached this active class.

[00:08:51] So this is really nice when you want to attach a specific style to let's say a button, to indicate that this is the current place that you are in the application. And then at the bottom, you have your router-outlet. And so this is where Angular is dynamically saying we have a route match to state this component and put it in here.

[00:09:13] So the question is, is what would be the point of having inactive state? And this is typically for, if you want to style, you wanna attach like a CSS class to let's say you have a row of buttons. Like let's say home courses, users, whatever. And if you're on the courses route, you wanna indicate like this is the currently selected route.

[00:09:40] So you might wanna maybe make that button just a little bit darker or possibly even disable it. So all it's doing is it's just detecting, if this is matched to the route that's defined by the routerLink, we're going to go ahead and attach whatever class you define for it.

[00:09:59] And so this is where, again, for stylistic reasons, you might want to just visually style that a little bit differently. So, the question is why do you need to import modules twice? I believe, so one for ES6 and one for Ngmodule. And the distinction that I wanna make there is that, you're using ES6 at the language level.

[00:10:25] So when you're writing your code and it compiles that by using Typescript and ES6, this is how the compiler knows that these things go together. And this is available. So this is ES6 modules are purely for compilation and language level purposes. On the other hand, Ngmodules, which are not at the language level they're at the framework level.

[00:10:54] These tell Angular specifically how to wire itself together. And so one is a language which is ES6. And then on top of that, you have Ngmodule which then tells Angular like, okay, in order for this to run, you have these dependencies and you have these particular components that we need to declare, as well as, let me go one module over here.

[00:11:26] So you'll notice even in the My routes, it's recommended that you actually segment that into a standalone module. And you'll see here that in the imports line so, I believe it's four lines from the bottom, is I am importing my routes into this module so it can be wired up by Angular.

[00:11:47] But I'm doing this by calling a method. And so I'm saying I want to attach these routes to essentially the root injector and make this available. And so this is specific to Angular when you see something like some module for route or for child that is specifically for Angular and how it assembles itself at runtime in order for it to work.

[00:12:13] So they, they're similar in terms of terminology, it's a bit overloaded, but they do two totally separate things. So language level organization, framework level organization. So the question is, what type of route would somebody lazy load? And the answer to that is possibly a route that does not get a lot of traffic.

[00:12:39] So when you don't lazy load your routes that everything gets compiled into like one bundle that gets deployed. That makes the initial payload a lot bigger. So let's say 80% of your application traffic is within one or two modules. So you might wanna load those up front to allow for a quicker load time.

[00:13:05] But then let's say once in a while, somebody actually does go and read your terms and conditions on your website. So that's actually a great one, is let's say if you have some terms and conditions or something that most people are not going to go to, but they need to be able to.

[00:13:27] And so you would load that lazily. So it's essentially on demand versus we're just gonna load everything up front preemptively.