How to access host component from directive?

前端 未结 6 453
北荒
北荒 2020-12-08 01:56

Say I have the following markup:


Is there any way I can access the component instance

相关标签:
6条回答
  • 2020-12-08 02:31

    Your directive could be the generic one that can be applied to any of your components. So, in that case, injecting the component in constructor would not be possible, So here is one other way to do the same

    Inject the ViewContainerRef in constructor

    constructor(private _viewContainerRef: ViewContainerRef) { }
    

    and then get it using

    let hostComponent = this._viewContainerRef["_data"].componentView.component;
    
    0 讨论(0)
  • 2020-12-08 02:40
    constructor(private vcRef: ViewContainerRef){
            let parentComponent=(<any>this.vcRef)._view.context;
    }
    
    0 讨论(0)
  • 2020-12-08 02:42

    If you want to use the attribute directive on your custom components you could have those components extend from an abstract class and 'forwardRef' the abstract class type to your component type. This way you can make angular's DI select on the abstract class (within 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... :-)
      }
    
    }
    

    This way you can use the directive on any component that extends your abstract class.

    This will of course only work on your own components.

    0 讨论(0)
  • 2020-12-08 02:46

    I do like this, it works on Angular 9.

    export class FromItemComponentBase  {
      constructor(private hostElement: ElementRef) {
        hostElement.nativeElement.__component=this;
      }
    }
    

    @Component({
      selector: 'input-error',
      templateUrl: 'component.html'
    })
    export class FromItemErrorComponent extends FromItemComponentBase {
      constructor(private hostElement: ElementRef) {
        super(hostElement);
      }
    }
    
    @Component({
      selector: 'input-password',
      templateUrl: 'component.html'
    })
    export class FromItemPasswordComponent extends FromItemComponentBase {
      constructor(private hostElement: ElementRef) {
        super(hostElement);
      }
    }
    

    @Directive({selector: 'input-error,input-password,input-text'})
    export class FormInputDirective {
      component:FromItemComponentBase;
    
      constructor(private hostElement: ElementRef) {
        this.component=hostElement.nativeElement.__component;
      }
    }
    
    0 讨论(0)
  • 2020-12-08 02:47

    You can just inject it

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

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

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

    0 讨论(0)
  • 2020-12-08 02:50

    This is taken from the github issue and works like a charm. The downside is needing to know the components beforehand, but in your case you would need to know the methods you're using anyway.

    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

    0 讨论(0)
提交回复
热议问题