3

Is there a way to retrieve a custom @directive from an HTMLElement by code?

e.g. let's say that I have declared the following directive

@Directive({selector: '[appCustomDirective]'}) export class MyCustomDirective { public MyVariable: string; }

that is attached to a button:

<button appCustomDirective>My button<button>

if I have the button as an HTMLElement variable, Is there a way to:

  • check whether it has the appCustomDirective attached?
  • retrieve the instance of the directive?

1 Answer 1

2

You should be able to access the directive via the injector on the element you've returned.

The component:

@Component({
  selector: 'app-my-custom-component',
  template: `
    <button id="with-directive" appMyCustomDirective>Click Me</button>
    <button id="without-directive">Click Me Too</button>
  `
})
export class MyCustomComponent {
}

The directive:

@Directive({
  selector: '[appMyCustomDirective]'
})
export class MyCustomDirective {
  public myVariable = 'hello there!';
}

The test:

describe('MyCustomComponent', () => {
 let component: MyCustomComponent;
 let fixture: ComponentFixture<MyCustomComponent>;

 beforeEach(async(() => {
   TestBed.configureTestingModule({
     declarations: [
       MyCustomComponent,
       MyCustomDirective
     ]
   })
     .compileComponents();
 }));

 beforeEach(() => {
   fixture = TestBed.createComponent(MyCustomComponent);
   component = fixture.componentInstance;
   fixture.detectChanges();
 });

 it('displays a button with the directive', () => {
   const buttonWithDirective = fixture.debugElement.query(By.css('#with-directive'));
   const directiveInstance: MyCustomDirective = buttonWithDirective.injector.get(MyCustomDirective);
   expect(directiveInstance.myVariable).toBe('hello there!');

   const buttonWithoutDirective = fixture.debugElement.query(By.css('#without-directive'));
   //danger!! this will throw an exception because there is no directive
   //const directiveInstance: MyCustomDirective = buttonWithDirective.injector.get(MyCustomDirective);
 });
});
Sign up to request clarification or add additional context in comments.

2 Comments

Your answer is clear and very well documented. I am still missing a way to get the injector of an HTMLComponent though. (In your case, you are accessing the injector of a DebugElement). Any help with that?
Can you elaborate a bit on what is it you're trying to accomplish? Maybe provide a more specific example? Are you testing something? HTMLElement isn't an Angular interface, so an "HTMLElement" variable won't have an "injector" prop to get things the dependency injector provides.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.