带标题的省略号指令

Ellipsis directive with title

我有一个 Angular 指令,它在 ngOnInit 中添加样式 text-overflow: ellipsis; overflow: hidden; white-space: nowrap;,然后看起来像这样:

@Directive({ selector: 'ellipsis' })
class EllipsisDirective {
  ngAfterViewInit() {
    const el: HTMLElement = this.el.nativeElement;
    if (el.offsetWidth < el.scrollWidth) {
      el.setAttribute('title', el.innerText);
    }
  }
}

用法:<div ellipsis>Some Very Long Text Here</div>

问题:
在某些页面上,layout/components 不会在 'navigate' 上发生变化,只有数据会发生变化。目前该指令不接受 el.innerText 中的差异,因此保留旧的 .title 属性.

我也尝试过使用 Input() 并使用 ngOnChanges()。不过我宁愿不使用输入。

我可以让它与输入和 setTimeout 一起工作,但这几乎不是可行的方法。

我想应该从 official docs 开始。答案是使用 AfterViewChecked 生命周期事件。

AfterViewChecked
Respond after Angular checks the content projected into the directive/component.

Called after the ngAfterContentInit() and every subsequent ngDoCheck().

@Directive({ selector: '[appEllipsis]' })
export class EllipsisDirective implements OnInit, AfterViewChecked {
  private get hasOverflow(): boolean {
    const el: HTMLElement = this.el.nativeElement;
    return el.offsetWidth < el.scrollWidth;
  }

  constructor(
    private el: ElementRef,
    @Inject(PLATFORM_ID) private platformId: any,
  ) {}

  ngOnInit() {
    // class overflow: text-overflow: ellipsis; overflow: hidden; white-space: nowrap;
    this.el.nativeElement.classList.add('overflow');
  }

  ngAfterViewChecked() {
    const isBrowser = isPlatformBrowser(this.platformId);
    if (isBrowser) {
      if (this.hasOverflow) {
        this.el.nativeElement.setAttribute('title', this.el.nativeElement.innerText);
      } else {
        this.el.nativeElement.setAttribute('title', '');
      }
    }
  }
}