Get reference to a directive used in a component

我是研究僧i 提交于 2019-11-26 15:44:35

问题


I have a component whose template looks something like this:

<div [my-custom-directive]>Some content here</div>

I need access to the MyCustomDirective class instance used here. When I want to get access to a child component, I use a ViewChild query.

Is there an equivalent feature to get access to a child directive?


回答1:


You can use exportAs property of the @Directive annotation. It exports the directive to be used in the parent view. From the parent view, you can bind it to a view variable and access it from the parent class using @ViewChild().

Example With a plunker:

@Directive({
  selector:'[my-custom-directive]',
  exportAs:'customdirective'   //the name of the variable to access the directive
})
class MyCustomDirective{
  logSomething(text){
    console.log('from custom directive:', text);
  }
}

@Component({
    selector: 'my-app',
    directives:[MyCustomDirective],
    template: `
    <h1>My First Angular 2 App</h1>

    <div #cdire=customdirective my-custom-directive>Some content here</div>
    `
})
export class AppComponent{
  @ViewChild('cdire') element;

  ngAfterViewInit(){
    this.element.logSomething('text from AppComponent');
  }
}

Update

As mentioned in the comments, there is another alternative to the above approach.

Instead of using exportAs, one could directly use @ViewChild(MyCustomDirective) or @ViewChildren(MyCustomDirective)

Here is some code to demonstrate the difference between the three approaches:

@Component({
    selector: 'my-app',
    directives:[MyCustomDirective],
    template: `
    <h1>My First Angular 2 App</h1>

    <div my-custom-directive>First</div>
    <div #cdire=customdirective my-custom-directive>Second</div>
    <div my-custom-directive>Third</div>
    `
})
export class AppComponent{
  @ViewChild('cdire') secondMyCustomDirective; // Second
  @ViewChildren(MyCustomDirective) allMyCustomDirectives; //['First','Second','Third']
  @ViewChild(MyCustomDirective) firstMyCustomDirective; // First

}

Update

Another plunker with more clarification




回答2:


It appears that since @Abdulrahman's answer, directives can no longer be accessed from @ViewChild or @ViewChildren as these pass only items on the DOM element itself.

Instead, you must access directives using @ContentChild/@ContentChildren.

@Component({
    selector: 'my-app',
    template: `
    <h1>My First Angular 2 App</h1>

    <div my-custom-directive>First</div>
    <div #cdire=customdirective my-custom-directive>Second</div>
    <div my-custom-directive>Third</div>
    `
})
export class AppComponent{
  @ContentChild('cdire') secondMyCustomDirective; // Second
  @ContentChildren(MyCustomDirective) allMyCustomDirectives; //['First','Second','Third']
  @ContentChild(MyCustomDirective) firstMyCustomDirective; // First
}

There is also no longer a directives property on @Component attribute.




回答3:


The sole remaining solution as of 2019

As mentioned in the comments of the other answers, these other (previously valid) methods would not work with the more recent versions of Angular.


Rejoice, however, for there is an even simpler way to get it injected: directly from the constructor!

@Component({
   // ...
})
export class MyComponent implements OnInit {

  // Would be *undefined*
  // @ContentChild(MyDirective, { static: true })
  // private directive: MyDirective;

  constructor(private directive: MyDirective) { }

  ngOnInit(): void {
    assert.notEqual(this.directive, null); // it passes!
  }
}

Additionally, you can add multiple annotations to tell the Dependency Injection engine where to look for the content to inject, using @Self or @Optional for example 🙂



来源:https://stackoverflow.com/questions/36345618/get-reference-to-a-directive-used-in-a-component

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!