Search code examples
angulartypescriptangular2-templateangular2-directivesangular2-components

Angular2 - What is the best practice to notify a directive when a component is updated?


I have a tooltip directive thar uses a component as its template. While creating the component dynamicly, the tooltip DOM element is not ready yet with its innerHtml. The component will get its real width for example only after ngAfterViewInit event.

But the directive don't know when the component template has completed rendering. Can I watch the private argument of a component (from directive) and know when its being changed/updated?

tootlipComponentTemplate

@Component({
  selector: 'tooltip-container',
  template: `<div #tooltipContent  [innerHTML]="htmlStr"></div>`
})
export class TooltipContainer implements AfterViewInit {

  @ViewChild('tooltipContent') elementRef: ElementRef;

  width: number;   
  htmlStr: string;

  constructor() {}

  ngAfterViewInit() { // this is the place when I really getting the tooltip width
    console.log("ngAfterViewInit: " + this.elementRef.nativeElement.offsetWidth);
    this.width = this.elementRef.nativeElement.offsetWidth;
  }

}

tooltipDirective

@Directive({
  selector: '[myTooltip]'
})
export class myTooltipDirective {

  private tooltip: ComponentRef<TooltipContainer>;
  private innerHtml: string;

  @HostListener("mouseenter", ['$event'])
  show(event:MouseEvent): void {

    // .. creating the tooltip with factory ..

    console.log(this.tooltip.instance.width); // its undefined at this point !!! //

  }


  constructor() {}      

}

HTML

<div [myTooltip]="myTextOrHtml">text with tooltip on mouseOver</div>

Solution

  • You can add an @Output() to your directive to notify the host component

    export class TooltipContainer implements AfterViewInit {
    
      @Output()
      domReady:EventEmitter = new EventEmitter();
      @ViewChild('tooltipContent') elementRef: ElementRef;
    
      ngAfterViewInit() { // this is the place when I really getting the tooltip width
        console.log("ngAfterViewInit: " + this.elementRef.nativeElement.offsetWidth);
        this.width = this.elementRef.nativeElement.offsetWidth;
        this.domReady.next(null);
      }
    
    <div [myTooltip]="myTextOrHtml" (domReady)="notifyParent()">text with tooltip on mouseOver</div>