How to dynamically add a directive?

RichieRock picture RichieRock · Dec 23, 2016 · Viewed 38.4k times · Source

How to dynamically add (inject) a directive into host?

I have a myTooltip directive and I would like to add mdTooltip directive to it's host. I have tried setAttribute() of ElementRef.nativeElement, but it doesn't create the mdTooltip directive.

mytooltip.directive.ts:

@Directive({
  selector: '[my-tooltip]',
  host: {
    '(mouseenter)': 'show()',
    '(mouseleave)': 'hide()',
  }
})
export class myTooltip {
  @Input('my-tooltip') message;

  constructor() { }

  show() {
    /* TODO: How to add md-tooltip directive to elementref (host)? */
  }

  hide() {
    /* TODO: remove md-tooltip directive from elementref (host) */
  }
}

By host I mean the element that has myTooltip directive:

<span my-tooltip="tooltip hint">Click here</span>

The result wouldn't change above html but on mouseenter it would have md-tooltip directive in span.

BTW, the reason I am using a wrapper and not directly md-tooltip is that I want to later modify the showing delay, hiding delay and customize material tooltip's behaviour in other means as well.

Edit Apparently adding directives dynamically is not currently supported :( I think this question should still be here in case it material team updates that

Answer

coderdark picture coderdark · May 3, 2017

That is a feature we are asking for in angular...read this: https://github.com/angular/angular/issues/8785

A quick and dirty way to do it is to use:

I have a directive named myHilite (to highlight text), I also have a component named MainComponent.ts. In MainComponent.ts I added this line of code...

export class MainComponent {
    @HostBinding('attr.myHilite') myHiliteDirective = new myHilite();
} 

If your directive requires parameters...

export class MainComponent {
    @HostBinding('attr.myHilite') myHiliteDirective = new myHilite(this.elementRef);
}

Your directive may need to execute code in one of its life cycle hooks, manually call the directive's lifecycle hook method in the parent component's lifecycle hook method like this...

export class MainComponent {
    //...code...

    ngOnInit(){
        this.myHiliteDirective.ngOnInit();
    }
}