File

projects/rebirth-ng/src/lib/tooltip/tooltip.ts

Implements

OnInit OnDestroy

Index

Properties
Methods
Inputs
HostListeners

Constructor

constructor(viewContainerRef: ViewContainerRef, elementRef: ElementRef, componentFactoryResolver: ComponentFactoryResolver, injector: Injector, positionService: PositionService, renderer: Renderer2, rebirthNGConfig: RebirthNGConfig)
Parameters :
Name Type Optional
viewContainerRef ViewContainerRef no
elementRef ElementRef no
componentFactoryResolver ComponentFactoryResolver no
injector Injector no
positionService PositionService no
renderer Renderer2 no
rebirthNGConfig RebirthNGConfig no

Properties

listens
listens: Function[]
Type : Function[]
Default value : []
popupRef
popupRef: ComponentRef<T>
Type : ComponentRef<T>
positionChange
positionChange:
Default value : new EventEmitter<any>()
tooltipPopupType
tooltipPopupType: Type<T>
Type : Type<T>
triggers
triggers: object
Type : object
Default value : { hover: ['mouseenter', 'mouseleave'], focus: ['focusin', 'focusout'], click: ['click'], manual: [] }

Methods

Protected fillPopup
fillPopup()
Returns : T
getContent
getContent()
Returns : string | TemplateRef
hide
hide()
Returns : void
ngOnDestroy
ngOnDestroy()
Returns : void
ngOnInit
ngOnInit()
Returns : void
Private positionTooltip
positionTooltip()
Returns : void
Private registerTriggers
registerTriggers()
Returns : void
Private removePopView
removePopView()
Returns : void
show
show()
Returns : void
toggle
toggle()
Returns : void

Inputs

appendBody

Default value: false

context

Type: any

cssClass

Type: string

placement

Type: "top" | "bottom" | "left" | "right"

Default value: 'top'

trigger

Type: "hover" | "click" | "manual"

Default value: 'hover'

HostListeners

document:click
Arguments : '$event'
document:click($event: Event)
import {
  OnInit,
  Input,
  ViewContainerRef,
  ComponentFactoryResolver,
  Injector,
  ComponentRef,
  ElementRef,
  Renderer2,
  HostListener,
  TemplateRef,
  OnDestroy,
  Type,
  EventEmitter
} from '@angular/core';
import { PositionService } from '../position/positioning.service';
import { TooltipPopup } from './tooltip-popup';
import { RebirthNGConfig } from '../rebirth-ng.config';
import { debounceTime, distinctUntilChanged, filter } from 'rxjs/operators';

export abstract class Tooltip<T extends TooltipPopup> implements OnInit, OnDestroy {
  @Input() context: any;
  @Input() cssClass: string;
  @Input() appendBody = false;
  @Input() trigger: 'hover' | 'click' | 'manual' = 'hover';
  @Input() placement: 'top' | 'bottom' | 'left' | 'right' = 'top';
  popupRef: ComponentRef<T>;
  triggers = {
    hover: ['mouseenter', 'mouseleave'],
    focus: ['focusin', 'focusout'],
    click: ['click'],
    manual: []
  };
  listens: Function[] = [];
  tooltipPopupType: Type<T>;
  positionChange = new EventEmitter<any>();

  constructor(protected viewContainerRef: ViewContainerRef,
              protected elementRef: ElementRef,
              protected componentFactoryResolver: ComponentFactoryResolver,
              protected injector: Injector,
              protected positionService: PositionService,
              protected renderer: Renderer2,
              protected rebirthNGConfig: RebirthNGConfig) {
  }

  abstract getContent(): string | TemplateRef<any>;

  ngOnInit() {
    const factory = this.componentFactoryResolver.resolveComponentFactory<T>(this.tooltipPopupType);
    const viewContainerRef = this.appendBody ? this.rebirthNGConfig.rootContainer : this.viewContainerRef;
    // EXCEPTION: Expression has changed after it was checked when append to body;

    setTimeout(() => {
      this.popupRef = viewContainerRef.createComponent(factory, 0, this.injector);
      this.fillPopup();
      this.registerTriggers();
      this.positionChange
        .pipe(
          filter(() => this.popupRef && this.popupRef.instance.isOpen),
          debounceTime(100),
          distinctUntilChanged()
        )
        .subscribe(() => this.positionTooltip());
    });

    this.listens.push(this.renderer.listen('window', 'resize', ($event) => this.positionChange.emit($event)));
    if (this.appendBody) {
      this.listens.push(this.renderer.listen('window', 'scroll', ($event) => this.positionChange.emit($event)));
    }
  }

  @HostListener('document:click', ['$event'])
  onDocumentClick($event: Event) {
    if (this.trigger !== 'manual') {
      const hostElement = this.elementRef.nativeElement;
      if (!hostElement.contains($event.target)) {
        this.hide();
      }
    }
  }

  ngOnDestroy(): void {
    this.listens.forEach(unregister => unregister());
    this.removePopView();
  }

  private removePopView() {
    if (this.popupRef) {
      this.popupRef.destroy();
    }
  }

  toggle() {
    if (this.popupRef.instance.isOpen) {
      return this.hide();
    }

    this.show();
  }

  show() {
    this.fillPopup();
    this.popupRef.instance.show();
    this.positionTooltip();
  }

  hide() {
    if (this.popupRef) {
      const popupComponent = this.popupRef.instance;
      popupComponent.hide();
    }
  }

  private registerTriggers() {
    const hostElement = this.elementRef.nativeElement;
    const trigger = this.triggers[this.trigger];
    if (trigger[0]) {
      this.listens.push(this.renderer.listen(hostElement, trigger[0], (event) => {
        this.show();
      }));
    }
    if (trigger[1]) {
      this.listens.push(this.renderer.listen(hostElement, trigger[1], ($event) => {
        this.hide();
      }));
    }
  }

  private positionTooltip() {
    const hostElement = this.elementRef.nativeElement;
    const targetElement = this.popupRef.location.nativeElement;
    const clientRect = this.positionService.positionElements(hostElement, targetElement, this.placement, this.appendBody);
    this.renderer.setStyle(targetElement, 'left', `${clientRect.left}px`);
    this.renderer.setStyle(targetElement, 'top', `${clientRect.top}px`);
  }

  protected fillPopup(): T {
    const popupComponent = this.popupRef.instance;
    popupComponent.content = this.getContent();
    popupComponent.cssClass = this.cssClass;
    popupComponent.context = this.context || {};
    popupComponent.placement = this.placement;
    return popupComponent;
  }
}

results matching ""

    No results matching ""