I have a directive with the following code
import { Directive, Input, OnInit, ElementRef, SimpleChanges, OnChanges } from '@angular/core';
import tippy from 'tippy.js';
@Directive({
selector: '[tippy]'
})
export class TippyDirective implements OnInit, OnChanges {
@Input('tippyOptions') public tippyOptions: Object;
private el: any;
private tippy: any = null;
private popper: any = null;
constructor(el: ElementRef) {
this.el = el;
}
public ngOnInit() {
this.loadTippy();
}
public ngOnChanges(changes: SimpleChanges) {
if (changes.tippyOptions) {
this.tippyOptions = changes.tippyOptions.currentValue;
this.loadTippy();
}
}
public tippyClose() {
this.loadTippy();
}
private loadTippy() {
setTimeout(() => {
let el = this.el.nativeElement;
let tippyOptions = this.tippyOptions || {};
if (this.tippy) {
this.tippy.destroyAll(this.popper);
}
this.tippy = tippy(el, tippyOptions, true);
this.popper = this.tippy.getPopperElement(el);
});
}
}
And using the directive as follows
<input tippy [tippyOptions]="{
arrow: true,
createPopperInstanceOnInit: true
}" class="search-input" type="text"
(keyup)="searchInputKeyDown($event)">
How can I have the Tippy shown on mouseenter or focus as these are the default triggers, from the tippy instance I have in the directive, this is what I get when I put console.log(this.tippy)
on line 44
{
destroyAll:ƒ destroyAll()
options:{placement: "top", livePlacement: true, trigger: "mouseenter focus", animation: "shift-away", html: false, …}
selector:input.search-input
tooltips:[]
}
As I am getting an error when I try to use
this.popper = this.tippy.getPopperElement(el);
ERROR TypeError: _this.tippy.getPopperElement is not a function
How can I get this directive to work as I took it from a repo in github
https://github.com/tdanielcox/ngx-tippy/blob/master/lib/tippy.directive.ts
What is it that I am missing here, any help is appreciated, thanks
I'm not sure what they were trying to accomplish in the linked repo you have included. To get tippy.js
to work though, you should be able to change the directive to the following:
import { Directive, Input, OnInit, ElementRef } from '@angular/core';
import tippy from 'tippy.js';
@Directive({
/* tslint:disable-next-line */
selector: '[tippy]'
})
export class TippyDirective implements OnInit {
@Input('tippyOptions') public tippyOptions: Object;
constructor(private el: ElementRef) {
this.el = el;
}
public ngOnInit() {
tippy(this.el.nativeElement, this.tippyOptions || {}, true);
}
}
Working example repo
This works with tippy.js 6.x
@Directive({selector: '[tooltip],[tooltipOptions]'})
export class TooltipDirective implements OnDestroy, AfterViewInit, OnChanges {
constructor(private readonly el: ElementRef) {}
private instance: Instance<Props> = null;
@Input() tooltip: string;
@Input() tooltipOptions: Partial<Props>;
ngAfterViewInit() {
this.instance = tippy(this.el.nativeElement as Element, {});
this.updateProps({
...(this.tooltipOptions ?? {}),
content: this.tooltip,
});
}
ngOnDestroy() {
this.instance?.destroy();
this.instance = null;
}
ngOnChanges(changes: SimpleChanges) {
let props = {
...(this.tooltipOptions ?? {}),
content: this.tooltip,
};
if (changes.tooltipOptions) {
props = {...(changes.tooltipOptions.currentValue ?? {}), content: this.tooltip};
}
if (changes.tooltip) {
props.content = changes.tooltip.currentValue;
}
this.updateProps(props);
}
private updateProps(props: Partial<Props>) {
if (this.instance && !jsonEqual<any>(props, this.instance.props)) {
this.instance.setProps(this.normalizeOptions(props));
if (!props.content) {
this.instance.disable();
} else {
this.instance.enable();
}
}
}
private normalizeOptions = (props: Partial<Props>): Partial<Props> => ({
...(props || {}),
duration: props?.duration ?? [50, 50],
});
}
Using this looks like:
<button [tooltip]="'Hello!'">Hover here</button>
<button [tooltip]="'Hi!'" [tooltipOptions]="{placement: 'left'}">Hover here</button>
You can also use the lifecyle hook ngAfterViewInit then you don't need the setTimeout.
public ngAfterViewInit() {
this.loadTippy();
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With