Angular 4 call directive method from component
Asked Answered
I

2

28

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

Innermost answered 29/8, 2017 at 20:9 Comment(2)
its not going to be possible without having the directive in the template. What you want is more a helpermethod/class than a directive.Ape
could you provide me an example.Innermost
C
38

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
}
Chairmanship answered 29/8, 2017 at 20:20 Comment(8)
Thanks. can we do without the additional div element. However i didn't get the expected result even with the above solution.Innermost
you need to have the directive applied to some element. you can use ng-container instead of div, it's rendered as a comment. what do you mean you didn't get the expected result? what is this.dirs.length? when do you call the click()?Chairmanship
i've updated my question. please check and provide me if we can achieve the requirement.Innermost
@mperle, if there's no directive in the component template Angular won't process it. Why is the requirement to not use directive in the template? With ng-container tag you will not clutter template in any wayChairmanship
@mperle, any comment?Chairmanship
yes, i agree with your point. I achieved it with the help of a component and a service. And that is the only way i see to meet my requirement.Innermost
saved my life :) #48267220Havre
This works perfectly fine with the ng-container approach! Thank you @MaxKoretskyiWariness
C
2

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()
}
Chemo answered 29/8, 2017 at 20:19 Comment(7)
Thank you for your answer. I tried this solution. But, i got console error 'cannot read property customDirective of undefined'Innermost
@Innermost can you tell me, where did you placed sampleDirective?Chemo
did you mean where the directive file is located or ?Innermost
@Innermost well, I meant to say where you used directive on HTML?Chemo
no thats the problem here. I don't want to use it inside any template. I want to call the method to make changes to dom. Is that possible ? I've updated the question.Innermost
@Innermost I don't understand how directive can work, without keeping it on DOM. I guess you talking about service, which can be standalone and reusable. But still not sure what you're looking for..Chemo
Let us continue this discussion in chat.Innermost

© 2022 - 2024 — McMap. All rights reserved.