2

I have the following template with a "dotdotdot" css class which add ellipsis on overflow correctly.

<div class="dotdotdot">{{data.trip.name}}</div>

What I'm trying to do here is to implement a directive which add a tooltip when the ellipsis is activated only.

Here is the current code from the directive:

import { Directive, OnInit, ElementRef } from '@angular/core';

declare var $: any;

@Directive({
  selector: '.dotdotdot'
})
export class DotdotdotDirective implements OnInit {

  private el: HTMLElement;
  constructor(elRef: ElementRef) {
    this.el = elRef.nativeElement;
}

ngOnInit() {           
         if (this.isEllipsisActive(this.el)) {   
            // TODO add title attribute to the div with value from text         
            $(this.el).tooltip();     
         }         
}

isEllipsisActive(e) {
     return (e.offsetWidth < e.scrollWidth);
}

}

I have two problems in the code above:

  1. isEllipsisActive is not working, I need the way to identified the ellipsis.
  2. I need to know how to add title or [title] attribute dynamically from $(this.el). The value is the text from the div.

Thanks!

user2304483
  • 945
  • 5
  • 16
  • 37
  • Possible duplicate of [HTML text-overflow ellipsis detection](https://stackoverflow.com/questions/7738117/html-text-overflow-ellipsis-detection) – tao Sep 24 '18 at 13:24
  • It works without jQuery. See [this stackblitz](https://stackblitz.com/edit/angular-problem-databinding-svyhec). – ConnorsFan Sep 24 '18 at 14:33
  • A bit more robust answer can be found [here](https://stackoverflow.com/a/55106043/540352). It works with `ngAfterViewChecked` so no `setTimeout` required + also clears the title if it is not necessary anymore when the `innerText` changes. – Laoujin Mar 11 '19 at 17:41

4 Answers4

9

You can create this directive:

import { AfterViewInit, Directive, ElementRef, EventEmitter, Output } from 

'@angular/core';

@Directive({
  selector: '[isEllipsisActive]'
})
export class IsEllipsisActiveDirective implements AfterViewInit {

  constructor(private elementRef: ElementRef) {}

  ngAfterViewInit(): void {
    setTimeout(() => {
      const element = this.elementRef.nativeElement;
      if(element.offsetWidth < element.scrollWidth){
        element.title = element.innerHTML;
      }
    }, 500);
  }
}

take a look on this https://stackblitz.com/edit/angular-qjmg7m?file=src%2Fapp%2Fis-ellipsis-active.directive.ts

ofir fridman
  • 2,501
  • 2
  • 15
  • 24
5

Great answer by ofir - Here's a modified version that will work if text changes after initialization.

import { Directive, ElementRef, HostListener } from '@angular/core';

@Directive({
  selector: '[isEllipsisActive]'
})

export class isEllipsisActiveDirective {

  constructor(private elementRef: ElementRef) {}

  @HostListener('mouseenter')
  onMouseEnter(): void {
    setTimeout(() => {
      const element = this.elementRef.nativeElement;
      if (element.offsetWidth < element.scrollWidth) {
        element.title = element.textContent;
      }
      else if (element.title) element.removeAttribute('title'); 
    }, 500);
  }
}
Chris
  • 988
  • 9
  • 13
0

You can use the disableTooltip property, and make a function for return if disable or not.

https://stackblitz.com/edit/sample-smart-tooltip

0
  isEllipsisActive(e: HTMLElement): boolean {
    return e ? (e.offsetWidth < e.scrollWidth) : false;
  }
<mat-card>
    <mat-card-title #galleryTitle [matTooltip]="gallery.name"
        [matTooltipDisabled]="!isEllipsisActive(galleryTitle)">
        {{gallery.name}}
    </mat-card-title>
<mat-card>
Austen Stone
  • 815
  • 1
  • 9
  • 19