Angular: Slice and *ngIf for Conditional Ellipsis / Tooltip on Data

Problem: Conditional Ellipsis without CSS

I want to add an ellipsis to data that's brought in from a service without having to use CSS' text-overflow: ellipsis feature, since it's unreliable and could break overtime if not monitored during refactoring.

Using Slice Pipe

Determine character max overflow limit

  • Determine max overflow by number of characters (instead of max-width)
  • Example: max overflow characters 20 (inclusive, aka 20 or more)
  • I use slice pipe where you add the start and end of the slice to the interpolated string
<!--Template-->
<a *ngFor="let item of items">
  {{ item.name | slice: 0 : 20 }}
</a>

Add ellipsis as conditional span

  • Conditional span is based on data's length
<!--Template-->
<a *ngFor="let item of items">
  {{ item.name | slice:0:20 }}<span *ngIf="item.name.length >= 20">...</span>
</a>

If Problems with String vs. Object

Sometimes typescript or certain db packages make this harder by making it so strings are but aren't considered strings. Solve this programmatically, by saving a new boolean value, when the data is either stored or updated:

// Component
onSave(event: any, item: Iitem): void {
  if (String(this.item.name).length >= 20) {
    this.item.maxChar == true;
  }
  if (event) {
    this.dataService.addItem(this.item);
  }
}

Thus, can then apply in template as

<!--Template-->
<span *ngIf="item.maxChar == true">...</span>

Show Tooltip Conditionally

I want the tooltip to appear when this maxChar is true; but to remove itself from the DOM when no longer hovering over the item.

<!--Template-->
<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>

<!--Tooltip-->
<div
  *ngIf="showsTooltip"
  [style.top]="tooltipTopY"
  [style.left]="tooltipLeftX"
  class="tooltip"
  >
  {{ tooltipText }}
</div>

Component

Catches coordinates of event and binds them

export class SomeComponent implements OnInit {
  // Properties
  showsTooltip = false; // show or not
  tooltipText = ''; // text to be binded
  tooltipTopY!: any;
  tooltipLeftX!: any;

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

67