Angular for Everyone: Part 11
How to use routing in Angular?
Why use Routing?
Hey, I know you are here because you have developed an extensive application, and you have forgotten to implements routing, or maybe you already know the basics, and you are just there to get some tips about it. In both cases, I’m going to try to help you as much as possible.
Why Routing?
Good question, Angular is defined as a single-page applications framework. However, Routing is recognized as a significant enhancement for the user experience. What’s more, you could use Guards, Resolvers which allows you to respect the separation of concerns more and greatly simplify your code.
By using lazy loading modules, you will maximize the performance of your application.
Anyway, we will talk about all of these points here in other chapters. I suggest starting this article with the basis.
Basic Routing
Default routing module generated on project creation
By default, when you create an Angular application without specifying options, you get by default the app-routing.module.ts.
_import_ { NgModule } _from_ '@angular/core';
_import_ { RouterModule, _Routes_ } _from_ '@angular/router';
_const_ routes: _Routes_ = []; (1)
@NgModule({
imports: [RouterModule._forRoot_(routes)], (2)
exports: [RouterModule]
})
_export class_ AppRoutingModule {}
This module is imported in your app.module.ts .
@NgModule({
declarations: [AppComponent],
imports: [BrowserModule, **AppRoutingModule** , ...], (3)
bootstrap: [AppComponent]
})
_export class_ AppModule {
}
And in the app.component.html, you have this (probably after the default generated code):
<router-outlet></router-outlet> (4)
Maybe we could just make a stop here to explain some points.
- Routes is just a type that corresponds to Route[] .
_export declare type Routes_ = _Route_[];
The route is an interface that defines requirements to represent a route. We will see all properties step by step.
- We use the RouterModule.forRoot first to import the module that handles the routing feature and give it which routes we have defined (none yet). It’s essential to use the forRoot because it’s the root’s routing definition of our application.
- Don’t forget to import the routing module in the associated feature module.
- RouterOutlet is the directive defined by Angular, which acts as a placeholder and is filled by Angular depending on the current router state.
Okay, I hope to lose anyone but don’t worry, we will see all of that with examples.
Our first basic routes
Suppose we have two domains in our app called feature-1 and feature-2. We would like to have direct access to the respective URLs:
Both have their associated entry point component called Feature1Component and Feature2Component.
Here’s how to define simple routes:
// app-routing.module.ts
_const_ routes: _Routes_ = [
{
path: 'feature-1', component: Feature1Component,
}, {
path: 'feature-2', component: Feature2Component,
}
];
Now you can directly access the desired URLs (http://localhost:4200/feature-1, http://localhost:4200/feature-2).
Yes, but I would like to go directly on feature-1 when I enter http://localhost:4200.
You are right, and we need to define a default root.
// app-routing.module.ts
_const_ routes: _Routes_ = [
{
path: 'feature-1', component: Feature1Component,
}, {
path: 'feature-2', component: Feature2Component,
}, {
**path: '', pathMatch: 'full', redirectTo: 'feature-1',**
}
];
Here, we defined that we want to redirect to the feature-1 way when there is no specified path. Don’t forget the pathMatch: ‘full,’ it allows us to indicate that we only want “no defined path” with the combination of the path.”
In HTML, we can use the URLs to get access to the pages:
<a _routerLink_="/feature-1">Feature 1</a>
<a _routerLink_="/feature-2">Feature 2</a>
Tips: How to know if the link is active or not ? You can use the RouterLinkActive directive like this:
<a _routerLink_="/feature-1" routerLinkActive="myCssClass" [routerLinkActiveOptions]="{exact: true}">Feature 1</a>
If the link matches exactly the current route, then the link will get the CSS class myCssClass. If the routerLinkActiveOptions: { exact: true } then it works like a match.
Route with children
Now, suppose that our feature-3 comprises two children sub-feature called sub-feature-3–1 and sub-feature-3–2 and not directly represented by one component as previously.
// app-routing.module.ts
_const_ routes: _Routes_ = [
{
path: 'feature-1', component: Feature1Component
}, {
path: 'feature-2', component: Feature2Component,
}, **{
path: 'feature-3', children: [
{
path: 'sub-feature-3-1',
component: Subfeature31Component
}, {
path: 'sub-feature-3-2',
component: Subfeature32Component
}, {
path: '',
redirectTo: 'sub-feature-3-1',
pathMatch: 'full' _// don't forget it_
}
]
}** , {
path: '', pathMatch: 'full', redirectTo: 'feature-1'
}
];
And in HTML:
<a _routerLink_="/feature-1">Feature 1</a>
<a _routerLink_="/feature-2">Feature 2</a>
<a _routerLink_="/feature-3">Sub Feature 3 1</a> <!-- Simplified there is a redirectTo -->
<a _routerLink_="/feature-3/sub-feature-3-2">Sub Feature 3 2</a>
Router service
The Router service provides navigation information and can be used to navigate from an URL to another one.
Tips: You can tracing all routing events if you want to debug and understand what is done during navigation:
@NgModule({
imports: [RouterModule._forRoot_(routes, {
enableTracing: !environment.production // just in dev mode
})],
exports: [RouterModule]
})
_export class_ AppRoutingModule {
}
If you want to navigate with the Router service, you just have to do this :
_this_.router.navigateByUrl('/feature-2');
or
_this_.router.navigate(['/feature-2']);
If you want to display a loading spinner during the navigation you can do something like:
// in app.component.ts
_private_ _isLoading$: BehaviorSubject<_boolean_> = _new_ BehaviorSubject<_boolean_>(_false_);
_constructor_(_private_ router: Router) {
}
_public_ ngOnInit(): _void_ {
_this_.router.events.pipe(
_filter_((event: _Event_) => event _instanceof_ NavigationStart)
).subscribe(() => _this_._isLoading$.next(_true_));
_this_.router.events.pipe(
_filter_((event: _Event_) => event _instanceof_ NavigationEnd)
).subscribe(() => _this_._isLoading$.next(_false_));
}
Define a 404 page
How to handle an unexisting URL in your application?
Once again, Angular provided for it. You can define a wildcard route like this:
// app-routing.module.ts
{
path: '**', component: PageNotFoundComponent
}
It means that if no route corresponds to the current requested URL then the displayed component will be PageNotFoundComponent.
Conclusion
Now you should be able to use routing in your application. Just tell me if you don’t. I know you are a bit frustrated, but I promise to quickly write articles about guards, resolvers, nested routes, and lazy loading ASAP.
Here you can access my project I use for medium articles:
GitHub - GaetanRdn/medium-angular: This project is a support for my medium articles.
Thanks for reading!
Top comments (0)