30

I'm trying to figure out how I can access the selector that we pass into the @Component decorator.

For example

@Component({
  selector: 'my-component'
})
class MyComponent {
  constructor() {
     // I was hoping for something like the following but it doesn't exist
     this.component.selector // my-component
  }
}

Ultimately, I would like to use this to create a directive that automatically adds an attribute data-tag-name="{this.component.selector}" so that I can use Selenium queries to reliably find my angular elements by their selector.

I am not using protractor

4 Answers 4

38

Use ElementRef:

import { Component, ElementRef } from '@angular/core'

@Component({
  selector: 'my-component'
})
export class MyComponent {
  constructor(elem: ElementRef) {
    const tagName = elem.nativeElement.tagName.toLowerCase();
  }
}
Sign up to request clarification or add additional context in comments.

1 Comment

This probably is the only way to do it now. The older (now broken) way was better since it didn't require adding an injection and it would be accessible without requiring an instance, which I use when writing end to end tests to minimize duplication.
14

Since Angualr v14.1 you can do this:

import { reflectComponentType } from '@angular/core';

@Component({
  selector: 'my-component'
})
class MyComponent {
  constructor() {
     const metadata = reflectComponentType(MyComponent);
     const selector = metadata.selector // my-component
  }
}

Comments

9

OUTDATED See https://stackoverflow.com/a/42579760/227299

You need to get the metadata associated with your component:

Important Note Annotations get stripped out when you run the AOT compiler rendering this solution invalid if you are pre compiling templates

@Component({
  selector: 'my-component'
})
class MyComponent {
  constructor() {
    // Access `MyComponent` without relying on its name
    var annotations = Reflect.getMetadata('annotations', this.constructor);
    var componentMetadata = annotations.find(annotation => {
      return (annotation instanceof ComponentMetadata);
    });
    var selector = componentMetadata.selector // my-component
  }
}

4 Comments

This looks promising, how is Reflect.getMetadata able to know that it's supposed to look for metadata for MyComponent if we're not telling it anything? I'm currently getting an error when I call Reflect.getMetadata('annotations'); The error is Reflect.getMetadata('annotations') VM61 angular2.sfx.dev.js:2652 Uncaught TypeError(…)getMetadata @ Reflect.getMetadata('annotations', this, 'annotations') It looks like it needs two extra parameters
Fixed your answer by passing this.constructor as the second argument.
Please qualify this answer with the version of Angular 2 to which it applies - as of release 2.3.0 this seems to be out-of-date
8

Here's an alternative if you need the selector name without access to the component's ElementRef:

const components = [MyComponent];

for (const component of components) {
  const selector = component.ɵcmp.selectors[0][0];
  console.log(selector);
}

Honestly, this first method feels rather hacky and who knows if this ɵ is supposed to just be for internal use? I thought I'd include it so that maybe someone could shed some light on it?

So, this is probably a safer route:

constructor(private factory: ComponentFactoryResolver) {
  const components = [MyComponent];

  for (const component of components) {
    const { selector } = this.factory.resolveComponentFactory(component);
    console.log(selector);
  }
}

3 Comments

The first solution depends on internal/private values. However, the second solution looks solid.
Second option is definitely the most solid option I've seen so far. Thanks for pointing that out drew
ComponentFactoryResolver is deprecated as of Angular v13. Which is a shame because I'm working with Angular elements and I could've used this to define the custom element in the AppModule constructor, so I can't inject the ViewContainerRef.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.