web-dev-qa-db-fra.com

Comment accéder au composant hôte depuis la directive?

Disons que j'ai le balisage suivant:

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

Est-il possible d'accéder à l'instance de composant à partir de la directive ?

Plus précisément, je souhaite pouvoir accéder aux propriétés et méthodes de MyComponent à partir de MyDirective, idéalement sans rien ajouter au code HTML ci-dessus .

13
AngularChef

Vous pouvez juste l'injecter

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

Une limitation importante est que vous devez connaître le type de composant à l’avance.

Voir aussi https://github.com/angular/angular/issues/8277
Il fournit également des solutions de contournement lorsque vous ne connaissez pas le type à l’avance.

18
Günter Zöchbauer

Ceci est tiré de la question github et fonctionne comme un charme. L'inconvénient est de connaître les composants à l'avance, mais dans votre cas, vous devez connaître les méthodes que vous utilisez de toute façon.

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");
                }
         }

Crédit: https://github.com/angular/angular/issues/8277#issuecomment-323678013

5
Anthony

Votre directive pourrait être la directive générique pouvant être appliquée à l’un de vos composants. Donc, dans ce cas, l'injection du composant dans le constructeur ne serait pas possible. Voici donc un autre moyen de faire de même

Injecte la ViewContainerRef dans le constructeur 

constructor(private _viewContainerRef: ViewContainerRef) { }

puis l'obtenir en utilisant 

let hostComponent = this._viewContainerRef["_data"].componentView.component;
4
Sunil Garg

Si vous souhaitez utiliser la directive attribut sur vos composants personnalisés, vous pouvez faire en sorte que ces composants s’étendent d’une classe abstraite et que le type de classe abstraite «forwardRef» s’applique à votre type de composant. De cette façon, vous pouvez faire en sorte que le DI de angular soit sélectionné dans la classe abstraite (dans votre directive).

Classe abstraite:

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

Composant personnalisé:

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

Directif:

@Directive({
  selector: '[appMyDirective]'
})
export class CustomDirective{

  constructor(private Host:MyReference) {
    console.log(this.Host);
    // no accessing private properties of viewContainerRef to see here... :-)
  }

}

De cette façon, vous pouvez utiliser la directive sur tout composant qui étend votre classe abstraite.

Cela ne fonctionnera évidemment que sur vos propres composants.

1
Michiel Windey