I am having an Angular 2 application with several nested children view. But it will be displayed on the same page though several router-outlet.
Create a Service called ActiveState:
import {Injectable} from "@angular/core";
import {Observable} from "rxjs";
@Injectable()
export class ActiveState {
public current : Observable;
private observer : any;
constructor()
{
// Create an observable (it can be subscribed to)
this.current = new Observable(observer => {
this.observer = observer;
observer.next('Unknown'); // The default unknown state
});
}
setActive(name : string) : void
{
this.observer.next(name);
}
}
In your resolvers such as PointListResolve ... TaskListResolve etc.
import {Resolve, ActivatedRouteSnapshot} from "@angular/router";
import {Injectable} from "@angular/core";
import {Observable} from "rxjs";
import {ActiveState} from "services/ActiveState.service";
@Injectable()
export class PointListResolver implements Resolve {
// Inject the ActiveState in your constructor
constructor(private state : ActiveState) {}
resolve(route: ActivatedRouteSnapshot): Observable {
// Set the active state name
this.state.setActive("Point"); // We are here: /queue/:date/:offset/:type/:bundleId/:pointId
// Do your regular resolve functionality (if you don't need to resolve, this blank resolver of an empty object will work)
// ...
return Observable.of({});
}
}
So in the other resolvers update the this.state.setActive("") value as required.
Then to determine which state you are in, inject ActiveState where you want to use the current state, such as in a @Component, i.e.
import {Component, OnDestroy} from '@angular/core';
import {ActiveState} from "services/ActiveState.service";
@Component({
selector: 'my-current-state-component',
template: `The current state is: {{stateName}}`,
})
export class MyCurrentStateComponent implements OnDestroy {
public stateName : string;
private sub : Subscription;
// Inject in ActiveState
constructor(private state : ActiveState)
{
// Subscribe to the current State
this.sub = state.current.subscribe(name => {
this.stateName = name;
// Other logic to perform when the active route name changes
...
});
}
ngOnDestroy()
{
this.sub.unsubscribe();
}
}
Notes:
Don't forget to register your ActiveState service as a Provider in:
@NgModule({
...
providers:[ActiveState]
...
})
export class AppModule { }
Simpler - Non-Observable Version I've used an Observable so changes to the active state can be subscribed to, but this could be simplified to just be a string if you don't want that functionality:
import {Injectable} from "@angular/core";
@Injectable()
export class ActiveState {
public current : string;
setActive(name : string) : void
{
this.current = name;
}
is(name : string) : boolean
{
return name == this.current;
}
}
Then when you inject state : ActiveState you can simple test the value state.is("Point")
I hope that's useful.