27

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

mperle
  • 3,342
  • 8
  • 20
  • 34

2 Answers2

36

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
}
Max Koretskyi
  • 101,079
  • 60
  • 333
  • 488
  • Thanks. can we do without the additional div element. However i didn't get the expected result even with the above solution. – mperle Aug 29 '17 at 20:33
  • 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()`? – Max Koretskyi Aug 29 '17 at 20:38
  • i've updated my question. please check and provide me if we can achieve the requirement. – mperle Aug 29 '17 at 20:44
  • 1
    @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 way – Max Koretskyi Aug 30 '17 at 05:12
  • @mperle, any comment? – Max Koretskyi Aug 30 '17 at 10:50
  • 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. – mperle Aug 31 '17 at 07:24
  • saved my life :) https://stackoverflow.com/questions/48266720/angular-directive-not-working-on-hidden-element – Marek Jan 15 '18 at 17:32
  • This works perfectly fine with the ng-container approach! Thank you @MaxKoretskyi – Panchakshari Puranmatt Jul 19 '22 at 07:32
0

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()
}
Pankaj Parkar
  • 134,766
  • 23
  • 234
  • 299
  • Thank you for your answer. I tried this solution. But, i got console error 'cannot read property customDirective of undefined' – mperle Aug 29 '17 at 20:28
  • @mperle can you tell me, where did you placed `sampleDirective`? – Pankaj Parkar Aug 29 '17 at 20:29
  • did you mean where the directive file is located or ? – mperle Aug 29 '17 at 20:35
  • @mperle well, I meant to say where you used directive on HTML? – Pankaj Parkar Aug 29 '17 at 20:36
  • 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. – mperle Aug 29 '17 at 20:40
  • @mperle 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.. – Pankaj Parkar Aug 29 '17 at 20:51
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/153175/discussion-between-mperle-and-pankaj-parkar). – mperle Aug 29 '17 at 21:46