Как получить доступ к компоненту хоста из директивы?
Скажем, у меня есть следующая разметка:
<my-comp myDirective></my-comp>
Есть ли способ получить доступ к экземпляру компонента из директивы?
В частности, я хочу иметь доступ к свойствам и методам MyComponent
из MyDirective
, идеально , не добавляя ничего в HTML выше.
Ответы
Ответ 1
Вы можете просто ввести его
class MyDirective {
constructor(private host:MyComponent) {}
Суровое ограничение состоит в том, что вам нужно заранее знать тип компонента.
См. также https://github.com/angular/angular/issues/8277
Он также предоставляет некоторые обходные пути, когда вы заранее не знаете тип.
Ответ 2
Это взято из проблемы GitHub и работает как шарм. Недостатком является то, что вам нужно знать компоненты заранее, но в вашем случае вам все равно придется знать методы, которые вы используете.
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");
}
}
Кредит: https://github.com/angular/angular/issues/8277#issuecomment-323678013
Ответ 3
Ваша директива может быть общей, которая может быть применена к любому из ваших компонентов. Таким образом, в этом случае инъекция компонента в конструкторе была бы невозможна. Итак, вот еще один способ сделать тот же
Вставить ViewContainerRef
в конструктор
constructor(private _viewContainerRef: ViewContainerRef) { }
а затем получить его с помощью
let hostComponent = this._viewContainerRef["_data"].componentView.component;
Ответ 4
constructor(private vcRef: ViewContainerRef){
let parentComponent=(<any>this.vcRef)._view.context;
}
Ответ 5
Если вы хотите использовать директиву атрибута в ваших пользовательских компонентах, вы можете сделать так, чтобы эти компоненты расширялись от абстрактного класса и 'forwardRef' - от абстрактного типа класса до типа вашего компонента. Таким образом, вы можете выбрать угловой DI для абстрактного класса (в вашей директиве).
Абстрактный класс:
export abstract class MyReference {
// can be empty if you only want to use it as a reference for DI
}
Пользовательский компонент:
@Component({
// ...
providers: [
{provide: MyReference, useExisting: forwardRef(() => MyCustomComponent)}
],
})
export class MyCustomComponent extends MyReference implements OnInit {
// ...
}
Директива:
@Directive({
selector: '[appMyDirective]'
})
export class CustomDirective{
constructor(private host:MyReference) {
console.log(this.host);
// no accessing private properties of viewContainerRef to see here... :-)
}
}
Таким образом, вы можете использовать директиву для любого компонента, расширяющего ваш абстрактный класс.
Это, конечно, будет работать только на ваших собственных компонентах.