Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get reference to a directive used in a component

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?

like image 407
Ben Dilts Avatar asked Mar 31 '16 23:03

Ben Dilts


People also ask

Can directive be used as component?

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.

How do you use directive in child components?

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 @directive in Angular?

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.

How do you pass a reference variable in a directive template?

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.


2 Answers

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

like image 68
Abdulrahman Alsoghayer Avatar answered Sep 23 '22 19:09

Abdulrahman Alsoghayer


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.

like image 30
Tobias J Avatar answered Sep 20 '22 19:09

Tobias J