23 June 2019
Angular (10) -- Routing
by Jerry Zhang
Day 18: Angular Routing
Register routes in app.module.ts
- Define a constant of Routes type, which should be imported from “@angular/router”.
const appRoutes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'users', component: UsersComponent },
{ path: 'servers', component: ServersComponent },
];
In the path, DO NOT add the slash /
. Just write path: 'users'
.
- Import the RouterModule and use
forRoot
to register our routes to the application.
imports: [
BrowserModule,
FormsModule,
RouterModule.forRoot(appRoutes)
],
<router-outlet></router-outlet>
as a placeholder in html file
Router links
Do not add the ref link in the tag. This will reload/refresh the page.
Use a directive routerLink
instead:
<li role="presentation" class="nav-item active"><a class="nav-link" routerLink="/">Home</a></li>
<li role="presentation" class="nav-item"><a class="nav-link" routerLink="/servers">Servers</a></li>
<li role="presentation" class="nav-item"><a class="nav-link" [routerLink]="['/users']" >Users</a></li>
Navigation paths
-
routerLink="/servers"
is an absolute path, always get appended to the root domain. -
routerLink="servers"
is a relative path, which will be appended after the currently loaded path. -
routerLink="./servers"
is the same as the second one, also a relative path. -
routerLink="../servers"
go back two paths.
Styling active router links
routerLinkActive
attribute can be added at the <a>
tag or <li>
tag, depending on the bootstrap version.
This style will be activated when this link is activated.
The routerLink defines on which path this element is binding with. It will be triggered on any path CONTAIN this path.
To prevent the home path, which is /
, always being triggered, we need to add routerLinkActiveOptions
configuration.
<li role="presentation" class="nav-item">
<a
class="nav-link"
routerLinkActive="active"
routerLink="/"
[routerLinkActiveOptions]="{exact: true}">Home</a>
</li>
Navigating Programmatically
Sometimes we want to do some logic before navigating. For example, we want to execute a function before navigating.
- Inject the router
constructor(private router: Router) { }
- Use this router in a function. Passing in an array of paths in the navigate() method.
onLoadServers() {
//Some calculation
this.router.navigate(['/servers']);
}
Config relative path in functions
By default, Angular does not know the current path. If we put a relative path in the navigate()
method, Angular
will always append this path after the root. However, we can change this by adding a relativeTo
configuration.
We firstly need to inject the ActivatedRoute in the constructor.
constructor(private serversService: ServersService,
private router: Router,
private route: ActivatedRoute) { }
onReload() {
this.router.navigate(['servers'], {relativeTo: this.route});
}
In this way, Angular understands that our currently activated route and then we are free to use relative path now.
Dynamic Paths
Passing parameters in path
Adding a colon after the /
in the path. Then id
becomes dynamic.
{ path: 'users/:id', component: UserComponent },
Retrieve the data from URLs.
Getting data from the URL can give us the ability to get information from the URL input by users directly. Not only we can go to the URL by programming, but also can typed by users.
- First of all, we need to inject the ActivatedRoute so that Angular knows the currently loaded route.
This currently loaded route is a Javascript object with a lot of metadata about this currently loaded route.
constructor(private route: ActivatedRoute) { }
- Because we want also the name of this user, so we append a
name
parameter in the app.module file.
{ path: 'users/:id/:name', component: UserComponent },
- Then, we can get the needed information by snapshot parameters.
ngOnInit() {
this.user = {
id: this.route.snapshot.params['id'],
name: this.route.snapshot.params['name']
};
}
- Now we are good to display this user in our html template.
<p>User with ID loaded.</p>
<p>User name is </p>
Fetching route parameters reactive
Construct a path with an array:
<a [routerLink]="['/users', 10, 'Anna']">Load Anna (10)</a>
This will generate a path /users/10/Anna
.
If we click this link navigating to the path above, the data on the screen is NOT updated! Why? Because we are already in this component. Angular will not reload the component even though we changed the url.
To let Angular know our subsequent changes, in our ngOnInit method, we should use the route to subscribe the changes.
ngOnInit() {
this.user = {
id: this.route.snapshot.params['id'],
name: this.route.snapshot.params['name']
};
this.paramsSubscription = this.route.params
.subscribe(
(params: Params) => {
this.user.id = params['id'];
this.user.name = params['name'];
}
);
}
this.route.params
is an “observable”. This is async procedure. This function is executed whenever the params
is
changed. Then we update our parameters.
Angular cleans up the subscription for us whenever this component is destroyed. However, it’s better to destroy this subscription manually by implement an OnDestroy method.
ngOnDestroy(): void {
this.paramsSubscription.unsubscribe();
}
In this case, actually Angular will do this for us. But, when we create our own observable, we have to remember to destroy it by hand. Therefore, it is a good manner to do this now.
tags: Angular