2021-12-15 10:17:07 +01:00
# Routing
Routes are a method to replace part of a page and display in the URL the desired component.
## Setup and Loading Routes
In the `app.module.ts` we need to register all the needed routes
```ts
import { Routers, RouterModule } from '@angular/router';
const appRoutes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'users', component: UsersComponent }, //localhost:4200/users
{ path: 'servers', component: ServersComponent },
];
@ngModule ({
imports: [
...,
RouterModule.forRoot(appRoutes)
]
})
```
`app.component.html`
```html
...
<!-- here we mark where we want to have the component rendered -->
< router-outlet > < / router-outlet >
...
```
## Navigating with router links
With every klicked Link, a new request is sent to the server and the **page** is refreshed.
> Bad implementation
```html
< ul class = "nav nav-tabs" >
< li role = "presentation" class = "active" > < a href = "/" > Home< / a > < / li >
< li role = "presentation" > < a href = "/servers" > Servers< / a > < / li >
< li role = "presentation" > < a href = "/users" > Users< / a > < / li >
< / ul >
```
> **Correct** implementation
```html
< ul class = "nav nav-tabs" >
< li role = "presentation" class = "active" > < a routerLink = "/" > Home< / a > < / li >
< li role = "presentation" > < a routerLink = "/servers" > Servers< / a > < / li >
< li role = "presentation" > < a routerLink = "/users" > Users< / a > < / li >
< / ul >
```
If there is more then one level the routeLink will look like this and it's called array-notation.
```html
< ul class = "nav nav-tabs" >
< li role = "presentation" class = "active" > < a routerLink = "/" > Home< / a > < / li >
< li role = "presentation" > < a routerLink = "/servers" > Servers< / a > < / li >
< li role = "presentation" > < a [ routerLink ] = " [ ' / users ' , ' editUser ' " > Users Edit< / a > < / li >
< / ul >
```
Result: https://domain.tld/user/editUser
Relative path: `servers` → Relative path will be added to the actual path.
Absolute path: `/servers`
## Styling active router links
`routerLinkActive="active"`
With `active` is the CSS-Class to style the active nav element.
```html
< ul class = "nav nav-tabs" >
< li role = "presentation"
routerLinkActive="active">< a routerLink = "/" > Home< / a > < / li >
< li role = "presentation"
routerLinkActive="active">< a routerLink = "/servers" > Servers< / a > < / li >
< li role = "presentation"
routerLinkActive="active">< a routerLink = "/users" > Users< / a > < / li >
< / ul >
```
This method has a caviat, that angular analyzes the URL and the Home is allways active because in every route contains the `domain.tld/`
By adding the `[routerLinkActiveOptions]="{exact: true}"` configuration, we can fix this issue. Necessary only on the `/`
```html
< ul class = "nav nav-tabs" >
< li role = "presentation"
routerLinkActive="active"
[routerLinkActiveOptions]="{exact: true}">< a routerLink = "/" > Home< / a > < / li >
...
< / ul >
```
## Trigger the routing programmatically
In any Component ts
```ts
import { Router } from '@angular/router'
export class HomeComponent {
// inject of the router
constructor(private router: Router) {}
onLoadServer() {
// some calc
this.router.navigate(['servers']);
}
}
```
## Passing parameter to Router
`:id` wil be dynamically assigned.
```ts
const appRoutes: Routes = [
{ path: '', component: HomeComponent },
{ path: 'users', component: UsersComponent }, //localhost:4200/users
{ path: 'users/:id', component: UserComponent }, //localhost:4200/users/5
{ path: 'servers', component: ServersComponent },
{ path: 'servers/:id', component: ServerComponent },
];
```
## Fetching Route Parameters
The data will be fetched from the URL `https://domain.tld/users/1/Max`
< img src = "../img/fetching_route_params.png" alt = "overview" width = "500" / >
`id` = 1
`name` = Max
```ts
this.route.snapshot.params.subscribe(
(params: Params) => {
this.user.id = params['id'];
this.user.name = params['name'];
}
);
```
If a route will change, the content of the Component will stay the same, because was allredy instanciated. If we want that the Component will update if the URL updates the `route.params` has to be used. It is of type `observable` and will act as asynchronus to load the data if and when the URL is changed.
If an instance gets destroyed and contains an observable which the component is subscribed to, is good practice to unsubscribe from it.
```ts
ngOnDestroy() {
this.paramsSubscription.unsubscribe();
}
```
## Passing query parameters and fragments
`servers.component.html`
```html
< a
[routerLink]="['/servers', server.id]"
[queryParams]="{allowEdit: server.id === 3 ? '1' : '0'}"
fragment="loading"
href="#"
class="list-group-item"
*ngFor="let server of servers">
{{ server.name }}
< / a >
```
## Retieving query parameters and fragments
```ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Params, Router } from '@angular/router';
@Component ({
selector: 'app-edit-server',
templateUrl: './edit-server.component.html',
styleUrls: ['./edit-server.component.css']
})
export class EditServerComponent implements OnInit, CanComponentDeactivate {
server: {id: number, name: string, status: string};
serverName = '';
serverStatus = '';
constructor(private serversService: ServersService,
private route: ActivatedRoute) {
}
ngOnInit() {
console.log(this.route.snapshot.queryParams);
console.log(this.route.snapshot.fragment);
this.server = this.serversService.getServer(id);
this.serverName = this.server.name;
this.serverStatus = this.server.status;
}
```