Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 - Check current active route "name"

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.

const routes: Routes = [
    {
        path: 'queue/:date/:offset/:type',
        component: BundleListComponent,
        resolve: {
            response: BundleListResolve
        },
        children: [
            {
                path: ':bundleId', component: PointListComponent,
                resolve: {
                    response: PointListResolve
                },
                children: [
                    {
                        path: ':pointId', component: TaskListComponent,
                        resolve: {
                            response: TaskListResolve
                        },
                        children: [
                            {
                                path: ':taskId', component: TaskDetailComponent,
                                resolve: {
                                    response: TaskDetailResolve
                                }
                            },
                            { path: '', component: EmptyComponent }
                        ]
                    },
                    { path: '', component: EmptyComponent }
                ]
            },
            { path: '', component: EmptyComponent }
        ]

    },
    {
        path: 'queue',
        component: QueueRedirectComponent
    }
}

So basically I can travel through the list of route

  • /queue
  • /queue/:date/:offset/:type
  • /queue/:date/:offset/:type/:bundleId
  • /queue/:date/:offset/:type/:bundleId/:pointId
  • /queue/:date/:offset/:type/:bundleId/:pointId/:taskId

For example

#/queue/2017-01-05/480/20/57f4c26507b36e3684007b52/1/57fb0abb07b36e39d8e88df8/1

Imagine you have a page with some element:

  1. One UI portion showed a movie list
  2. The other portion shows a movie detail when clicking into an item in a movie list but display on the same page.
  3. Another portion to show a character detail when clicking into character name on movie detail, and also show on the same page.
  4. etc...

Basically, I can still click into movie list while I am viewing a character detail.

Searching for defining the name for each route but seem all the answer report this feature has already removed from Angular 2 final. In Angular 1 using UI Router, I can define the name for each route and can get the route very easily with built-in function state.is(ROUTE_NAME).

So what I am doing now is base on the window.location to get the URL and splitting this string by / to get the number of parameters. But It's more hard-coded one.

Any experience on doing the same? How I can distinguish which route is currently active?

like image 665
trungk18 Avatar asked Jan 05 '17 15:01

trungk18


1 Answers

Create a service called ActiveState which will subscribe to changes to the router, using router.events.subscribe:

import {Injectable} from "@angular/core";
import {Router, ActivatedRoute, NavigationEnd} from "@angular/router";

@Injectable()
export class ActiveState {

  public name : string;

  constructor(router : Router, route : ActivatedRoute)
  {
    router.events.subscribe(event => {
      if(event instanceof NavigationEnd){

        // Traverse the active route tree
        var snapshot = route.snapshot;
        var activated = route.firstChild;
        if(activated != null) {
          while (activated != null) {
            snapshot = activated.snapshot;
            activated = activated.firstChild;
          }
        }

        // Try finding the 'stateName' from the data
        this.name = snapshot.data['stateName'] || "unnamed";
      }
    });
  }

  is(name : string) : boolean
  {
    return this.name === name;
  }
}

Then on your route we add a simple value on the data param of the route called stateName for each state we want to name:

const routes: Routes = [
{
    path: 'queue/:date/:offset/:type',
    component: BundleListComponent,
    resolve: { response: BundleListResolve }
    data: { stateName: 'Bundle' },
    children: [
        {
            path: ':bundleId', component: PointListComponent,
            resolve: { response: PointListResolve },
            data: { stateName: 'Point'}
        }
    ...

Then when you inject state : ActiveState you can simple test the value state.is("Point")

like image 139
Scott Avatar answered Oct 02 '22 16:10

Scott