10

Is there any way we can detect if the text is overflow in angular controller?

In my CSS I have the following code:

width: calc(100% - 60px);
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
  padding-top: 5px;

And I want to be able to detect if the text is overflow in the angular controller so I can display the tooltip for it. If the text is not overflow then no need to display the tooltip, which was the reason why I want to be able to detect if the text is overflow in the controller.

Sam Hanley
  • 4,707
  • 7
  • 35
  • 63
Kim
  • 315
  • 4
  • 7
  • 13

3 Answers3

18

There is no way for angular (or javascript in general) to know whether an element has used the "...". See this very similar question: HTML text-overflow ellipsis detection.

The best you can do is something like this (where you pass the element you care about in):

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

Js courtesy that link.

Community
  • 1
  • 1
Mathew Berg
  • 28,625
  • 11
  • 69
  • 90
3

In addition to Mathew's answer.

I applied that JavaScript logic to an angular 2+ implementation using material components. In this example, you can see that the same JS check is utilized to either disable or enable the Material Tooltip if the text was truncated.

<mat-expansion-panel-header 
            [matTooltipDisabled]="(titleContent.offsetWidth < matpanelTitle.scrollWidth)" 
            matTooltip="{{recording.alias}}">

    <mat-panel-title #matpanelTitle style="white-space: nowrap; 
                                           overflow: hidden; 
                                           text-overflow: ellipsis; 
                                           display: block;">

         <span #titleContent>
              {{recording.alias}}
         </span>

     </mat-panel-title>

</mat-expansion-panel-header>
NKS
  • 43
  • 4
1

Here's a bit of a cleaner solution I've found for this use-case. Instead of CSS, I used the slice angular pipe, where the two values mark the start and end of the sliced characters.

Angular Ellipsis with Slice and *ngIf

  • Slice pipe isolates first 20 characters
  • A span follows with a manually written "..." string
  • The ellipsis span is conditional on how many characters are showing using item.name.length and having it either be greater or equal to the number of characters allowed from the slice
<a *ngFor="let item of items">
  {{ item.name | slice: 0 : 20 }}<span *ngIf="item.name.length >=20">...</span>
</a>

Show Tooltip Conditionally

I also wanted this to display a tooltip. But I didn't want any other anchors to have a tooltip unless the ellipsis was present (since the tooltip would show the entire name)

Template
  • With mouseover, uses a ternary operator that triggers an onHover method IF it has equal or more characters than previous identified
  • The onHover method takes in both the $event and the name (string) of the item
  • Tooltip has styling required to appear at mouse coords (absolute) but binds component variables to [style.top] and [style.left] so it appears where mouse event fires
  • The (mouseout) ensures the tooltip is gone when no longer hovering over the element
<a
  *ngFor="let item of items"
  (mouseover)="(item.name.length >= 20) ? onHover($event, item.name) : '' "
  (mouseout)="showsTooltip ? (showsTooltip = !showsTooltip) : '' ">
  {{ item.name | slice: 0 : 20 }}<span *ngIf="item.name.length >=20">...</span>
</a>

<!-- some other code -->

<div
  *ngIf="showsTooltip"
  [style.top]="tooltipTopY"
  [style.left]="tooltipLeftX"
  class="tooltip"
  >
  {{ tooltipText }}
</div>
Component
  • Catches the coordinates from the event object and binds them accordingly
export class SomeComponent implements OnInit {
  showsTooltip = false;
  tooltipText = '';
  tooltipTopY!: any;
  tooltipLeftX!: any;

  // ... other code

  onHover(e: any, cardName: string): void {
    this.tooltipText = cardName;
    if (e) {
      this.showsTooltip = true;
      this.tooltipTopY = e.clientY + 'px';
      this.tooltipLeftX = e.clientX + 'px';
    }
  }
}

Hope this helps! Grateful for thorough answers that've helped me here; and I find this solution has been pretty clutch for me so far - so just hoping to share where I can!

Ria Pacheco
  • 151
  • 1
  • 3