I am building a calendar that can display different kinds of data. The following example explains my URL structure I think:
todo/2017/01/01
a day view of todosbirthdays/2017/01/01
a day view of birthdays todo/2017/01
a month view of todosbirthdays/2017/01
a month view of birthdaystodo/2017
a year view of todosbirthdays/2017
a year view of birthdaysUp until now I have be able to pass in a Date
object and reroute via
this.router.navigate([#HARDCODED# 'todo' #OR# 'birthday', year, ?month, ?day])
The problem is that I want to be able to navigate from todo/2017/01/01
=> birthdays/2017/01/01
OR todo/2017/01
=> birthdays/2017/01
.
So I can't pass in the date parameters because some may not exist depending on which view I am in.
So how can I only switch out a single, internal parameter and reroute?
Something like
this.router.navigate(['todo', {ignoreTheRest: true}])
Otherwise I have to write a complicated switch statement for every possible combination.
You can achieve this via the built-in ActivatedRoute
service, your "one-stop-shop for route information", as they say in the documentation.
First, you need to inject the service in your component's constructor. Assuming that you have a Todo component an a Birthday component, in either case the constructor would look like:
constructor(private currentRoute: ActivatedRoute, private router: Router) { }
Then, in your ngOnInit() function, you need to subscribe to your ActivatedRoute instance's url property, which is an Observable:
ngOnInit() {
this.currentRoute.url
.subscribe(routeParts => {
this.periodArray = [];
for (let i = 1; i < routeParts.length; i++) {
this.periodArray.push(routeParts[i].path);
}
});
}
The reason why your component route is provided as an Observable is that during your component's life cycle it can receive several different routes. Like in your case "/todo/2017" or "todo/2017/01" etc. Your component will only be created once, the ngOnInit() will also be called only once, but through subscribing to the ActivatedRoute.url observable, you will always get notified about the current route.
The above code block fills an array with all but the first url part from the activated route, which gives you all the passed parameters except for the initial "/todo" or "/birthday" segment.
Now you can navigate to the other component by simply adding the required path at the beginning of this parameter array, like:
navigateBirthdays() {
this.periodArray.unshift('/birthday');
this.router.navigate(this.periodArray);
}
Here is the full code for the Todo component and it's template:
todo.component.ts
import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
templateUrl: './todo.component.html',
})
export class TodoComponent implements OnInit {
periodArray = [];
constructor(private currentRoute: ActivatedRoute, private router: Router) { }
ngOnInit() {
this.currentRoute.url
.subscribe(routeParts => {
this.periodArray = [];
for (let i = 1; i < routeParts.length; i++) {
this.periodArray.push(routeParts[i].path);
}
});
}
navigateBirthdays() {
this.periodArray.unshift('/birthday');
this.router.navigate(this.periodArray);
}
}
todo.component.html
<p>
List of Todo items for {{periodArray.join("-")}}
</p>
<button (click)="navigateBirthdays()">Show Birthday items</button>
The Birthday component would look virtually identical. The above allows you to go back and forth between "/todo/2017/1/3" and "/birthday/2017/1/3" and also between "/todo/2017" and "/birthday/2017" etc. - without setting up any specific routing rules.
A side note: for optional parameters it is usually better not to include them in the URL path, but to provide them as an optional route object - see this section of the documentation.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With