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?
A component is a single unit that encapsulates both view and logic whereas directives are used to enhance the behavior of components or dom elements and it doesn't have any templates. Component extends directive so every component is a directive.
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() .
What is meant by directives in Angular? Directives are classes that add new behavior or modify the existing behavior to the elements in the template. Basically directives are used to manipulate the DOM, for example adding/removing the element from DOM or changing the appearance of the DOM elements.
We declare Template reference variables using # followed by the name of the variable ( #variable ). We can also declare them using #variable="customer" when the component/directive defines a customer as the exportAs Property.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With