Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Retrieving the active component and path

With Angular2, how would I retrieve the current active component and path?

For example I might have the following routes:

{ path: '', component: HomeComponent },
{ path: 'list', component: ListComponent },
{ path: ':id/', component: CustomComponent }

If I had navigated to https://domain.com/test is there a way to know I'm currently viewing the CustomComponent and to retrieve the id/path, which in this case is "test"?

I could use window.location.pathname with regex to get the path but this is messy and still doesn't allow me to easily get the active component.

like image 975
Joey Morani Avatar asked Jan 10 '17 23:01

Joey Morani


2 Answers

Yes you can check current active component using router snapshot-

import { Router,ActivatedRoute }      from '@angular/router';

constructor(public route : ActivatedRoute) {
    var snapshot = route.snapshot;
    console.log(snapshot._routeConfig.component.name); //This will give you the name of current active component
  }

Note- snapshot._routeConfig.component.name it will give you the active component name, and if you want url you can also get it by .url instead of name

like image 189
sachinkasana Avatar answered Nov 08 '22 05:11

sachinkasana


In ActivatedRouteSnapshot the component property is defined as being one of the following

component: Type<any> | string | null;

So you can't just do component.name unless you've already made sure you have Type<any>. This is because .name on a string doesn't exist.

Now Type<any> is actually a function that creates the type (your component type) and is defined as:

export interface Type<T> extends Function {
    new (...args: any[]): T;
}

So you can do something like this, which will actually compile

 if (typeof(this.route.snapshot.component) === 'function')
 {
     // the compiler is 'smart' enough to know that component here must be Type<T>
     const name = this.route.snapshot.component.name;
 }

An 'elegant' way to do it is using a typescript typeguard (although to be frank in this case it doesn't give you much of a benefit over what I just said).

isComponent(item: Type<any> | string | null): item is Type<any>
{
    return typeof item === 'function';
}

Then you can say this.name = isComponent(this.route.snapshot.component) ? this.route.snapshot.component : null.

Important: component.name is still valid in an AOT build, but unfortunately with --prod it will end up being something random like r.

I've resorted to having to inject private element: ElementRef<HTMLElement> and then look for the tag name. This will still be present even with an AOT prod build. There may be a performance cost to doing this so cache it if you're using it a lot.

    if (element.nativeElement.tagName.startsWith('RR-')){
        super.name = element.nativeElement.tagName;
    }
like image 21
Simon_Weaver Avatar answered Nov 08 '22 04:11

Simon_Weaver