How to access the host component from a directive?

Say I have the following markup:

<my-comp myDirective></my-comp> 

Is there a way to access a component instance from a directive ?

In particular, I want to have access to the MyComponent properties and methods from MyDirective , ideally without adding anything to the HTML above .

+13
source share
5 answers

You can just enter it

 class MyDirective { constructor(private host:MyComponent) {} 

A severe limitation is that you need to know the type of component in advance.

See also https://github.com/angular/angular/issues/8277
It also provides some workarounds when you don't know the type in advance.

+13
source

This is taken from the GitHub issue and works like a charm. The disadvantage is that you need to know the components in advance, but in your case, you still have to know the methods that you use.

 import { Host, Self, Optional } from '@angular/core'; constructor( @Host() @Self() @Optional() public hostCheckboxComponent : MdlCheckboxComponent ,@Host() @Self() @Optional() public hostSliderComponent : MdlSliderComponent){ if(this.hostCheckboxComponent) { console.log("host is a checkbox"); } else if(this.hostSliderComponent) { console.log("host is a slider"); } } 

Credit: https://github.com/angular/angular/issues/8277#issuecomment-323678013

+3
source

Your directive can be generic, which can be applied to any of your components. Thus, in this case, the injection of the component in the constructor would be impossible. So here is another way to do the same

Insert ViewContainerRef in constructor

 constructor(private _viewContainerRef: ViewContainerRef) { } 

and then get it using

 let hostComponent = this._viewContainerRef["_data"].componentView.component; 
+1
source
 constructor(private vcRef: ViewContainerRef){ let parentComponent=(<any>this.vcRef)._view.context; } 
0
source

If you want to use the attribute directive in your custom components, you can make these components expand from an abstract class and 'forwardRef' from an abstract class type to your component type. So you can choose the angular DI for the abstract class (in your directive).

Abstract class:

 export abstract class MyReference { // can be empty if you only want to use it as a reference for DI } 

Custom component:

 @Component({ // ... providers: [ {provide: MyReference, useExisting: forwardRef(() => MyCustomComponent)} ], }) export class MyCustomComponent extends MyReference implements OnInit { // ... } 

Directive:

 @Directive({ selector: '[appMyDirective]' }) export class CustomDirective{ constructor(private host:MyReference) { console.log(this.host); // no accessing private properties of viewContainerRef to see here... :-) } } 

Thus, you can use the directive for any component that extends your abstract class.

This, of course, will only work on your own components.

0
source

Source: https://habr.com/ru/post/1271453/


All Articles