Angular 4 call directive method from component

43.7k Views Asked by At

i'm trying to build a structural directive that will change the parent DOM structure either invoked by using its selector (static) or by calling its public method(dynamic).

  • Using the directive selector in a html template works fine without any issues.

  • I'm trying to figure out if we an achieve the same without using it in template and by calling the directive method.

my-directive.ts

@Directive({ selector: '[sampleDirective]' })

export class SampleDirective {
    ...
   constructor(..) {
        this.customDirective();
     }
  }
customDirective() {
    console.log('Inside customDirective()');
}

my-component.ts

import { SampleDirective } from './my.directive';
...
@Component({
 selector: 'my-component',
 template: `<button (click)="click()"> Click Me </button>`
})
constructor() { }
..
click() {
  // call directive method here
}

I need this because i'm creating a generic solution to change the DOM structure of a component at runtime with help of a directive.

** please ignore if there are any typo. sorry that i couldn't paste the complete code here

2

There are 2 best solutions below

8
Max Koretskyi On BEST ANSWER

If there's no directive in the component template Angular won't process it. With ng-container tag you will not clutter template in any way. To get the directive then use @ViewChildren/@ViewChild to get the instance of the directive:

@Component({
 selector: 'my-component',
 template: `<button (click)="click()"> Click Me </button>
            <ng-container sampleDirective></ng-container>`
})
@ViewChildren(SampleDirective) dirs;
constructor() { }
..
click() {
   this.dirs.first.customDirective();
  // call directive method here
}
7
Pankaj Parkar On

For calling directive method from component, you could use ViewChild decorator to locate directive instance on the page. Then by using the same you could access directive all props.

@ViewChild(SampleDirective) directive;
constructor() { }
..
click() {
  // call directive method here
  this.directive.customDirective()
}