问题背景
在项目中,由于支持了国际化,导致语言为英文时,部分文字会超出元素。故有些地方需要使用“…”方式来截断文字并显示气泡,当没有截断文字时不显示气泡,ng-zorro原生tooltip无法支持,需要继承该指令并自定义逻辑。
实现方案
继承NzTooltipDirective,完成初始化参数传递
export class VisibleTooltipDirective extends NzTooltipDirective implements AfterViewInit {
/**
* 初始化构造函数
*
* @param el 模版
* @param render
*/
constructor(
elementRef: ElementRef,
hostView: ViewContainerRef,
resolver: ComponentFactoryResolver,
renderer: Renderer2,
@Host() @Optional() noAnimation?: NzNoAnimationDirective
) {
super(elementRef, hostView, resolver, renderer, noAnimation);
}
/**
* dom渲染完成,可获取dom节点,重新实现NzTooltipBaseDirective钩子创建气泡
*/
ngAfterViewInit(): void {
this.createComponent();
this.registerTriggers();
}
}
通过判断元素clientWidth与scrollWidth的关系来控制气泡的显隐
/**
* 鼠标移入,判断是否显示气泡
* @returns
*/
@HostListener('mouseenter')
onMouseEnter(): void {
if (!this.nzDynamicVisibleTooltip) return;
if (this.elementRef.nativeElement.clientWidth >= this.elementRef.nativeElement.scrollWidth) {
this.hide(); // 继承自NzTooltipBaseDirective方法
} else {
this.show(); // 继承自NzTooltipBaseDirective方法
}
}
/**
* 鼠标移出,隐藏气泡
*/
@HostListener('mouseleave')
onMouseLeave(): void {
if (!this.nzDynamicVisibleTooltip) return;
this.hide(); // 继承自NzTooltipBaseDirective方法
}
💡 Tips:由于目前项目只是需要根据截断文字显隐气泡,故通过调用show和hide方法就能够实现。如有更复杂的需求,还可重写@Input属性和其余方法。也可以通过重写componentFactory自定义气泡组件。具体可以看看Tooltip源码(NzTooltipDirective、NzToolTipComponent、NzTooltipBaseDirective、NzTooltipBaseComponent)
export class VisibleTooltipDirective extends NzTooltipDirective implements AfterViewInit {
componentFactory: ComponentFactory<CustomToolTipComponent> = this.resolver.resolveComponentFactory(CustomToolTipComponent);
}
完整代码
import { Directive, ElementRef, Renderer2, ViewContainerRef, ComponentFactoryResolver, Host, Optional, AfterViewInit, Input, HostListener } from '@angular/core';
import { NzNoAnimationDirective } from 'ng-zorro-antd/core/no-animation';
import { NzTooltipDirective } from 'ng-zorro-antd/tooltip';
@Directive({
selector: '[appVisibleTooltip]'
})
export class VisibleTooltipDirective extends NzTooltipDirective implements AfterViewInit {
@Input() nzDynamicVisibleTooltip: boolean = true; // 用于判断是否使用自定义逻辑
/**
* 初始化构造函数
*
* @param el 模版
* @param render
*/
constructor(
elementRef: ElementRef,
hostView: ViewContainerRef,
resolver: ComponentFactoryResolver,
renderer: Renderer2,
@Host() @Optional() noAnimation?: NzNoAnimationDirective
) {
super(elementRef, hostView, resolver, renderer, noAnimation);
}
/**
* dom渲染完成,可获取dom节点
*/
ngAfterViewInit(): void {
// 配合截断文字动态显示气泡
if (this.nzDynamicVisibleTooltip) {
this.trigger = null;
}
this.createComponent();
this.registerTriggers();
}
/**
* 鼠标移入
* @returns
*/
@HostListener('mouseenter')
onMouseEnter(): void {
if (!this.nzDynamicVisibleTooltip) return;
if (this.elementRef.nativeElement.clientWidth >= this.elementRef.nativeElement.scrollWidth) {
this.hide();
} else {
this.show();
}
}
/**
* 鼠标移出
*/
@HostListener('mouseleave')
onMouseLeave(): void {
if (!this.nzDynamicVisibleTooltip) return;
this.hide();
}
}
💡 Tips:欢迎小伙伴们共同讨论更优方法哦!!!