Quote of the Day

more Quotes

Categories

Buy me a coffee

  • Home>
  • Angular>

Displaying text in a tool tip when text overflows its container

Published June 16, 2022 in Angular - 1 Comment

In several apps I work on, we use angular material to display data in a table. Sometimes, long text causes the height of the table cells to increase, resulting in an unaesthetic UI.

Using CSS, we can set the max width of the table cells, hide overflow and show ellipsis at the end of the overflowing text. When the user hovers over the long text, we can display the full content in a tooltip.

Below CSS snippet will instruct the browser to hide the overflow text and display with ellipsis.

 table {
   // .... codes omitted for brevity 
    td {
      overflow: hidden;
      text-overflow: ellipsis;
      white-space: nowrap;
      max-width: 400px;
      padding: 0px 10px;
    }
  }
}

In the above snippet, setting overflow to hidden and text-overflow to ellipsis allow the browser to replace the part of the text that cannot fit within the container with ellipsis. We set white-space to nowrap to collapse the whitespaces and avoid wrapping. Otherwise, the browser will break the text to another line as necessary, increasing the height of the table cells, which we don’t want.

In our app, we only want to display tooltip on table cells which contain overflowing text, not on all table cells. Below code snippets, which I took from this stackoverflow post, check when overflow occurs in an element.

  // Determines if the passed element is overflowing its bounds,
  // either vertically or horizontally.
  // Will temporarily modify the "overflow" style to detect this
  // if necessary.
  // https://stackoverflow.com/questions/143815/determine-if-an-html-elements-content-overflows
  isOverflow(el: HTMLElement): boolean {
    var curOverflow = el.style.overflow;

    if (!curOverflow || curOverflow === "visible")
      el.style.overflow = "hidden";

    var isOverflowing = el.clientWidth < el.scrollWidth
      || el.clientHeight < el.scrollHeight;

    el.style.overflow = curOverflow;

    return isOverflowing;
  }

In the html template, we can bind to the isOverflow method in the component to conditionally enable or disable the tooltip.

<div class="master-list-container">
  <table matSort mat-table [dataSource]="data" class="mat-elevation-z8">
    <ng-container *ngFor="let column of columns" [matColumnDef]="column">
      <th mat-header-cell *matHeaderCellDef [mat-sort-header]="column"> {{getDisplayName(column)}} </th>
      <ng-container>
        <td mat-cell #tdElement
            [class.row-highlight]="element.id === currentElement?.id"
            [matTooltip]="element[column]"
            [matTooltipDisabled]="!isOverflow(tdElement)"
            matTooltipPosition="below" matTooltipClass="tooltip" *matCellDef="let element">
          {{element[column]}}
        </td>
      </ng-container>
    <tr mat-header-row *matHeaderRowDef="columns"></tr>
    <tr mat-row *matRowDef="let row; columns: columns;"></tr>
  </table>
<!-- codes omitted for brevity --> 
</div>

In the above snippet, notice how we bind the matTooltipDisabled property to the isOverflow function in the component. We also declare the template variable #tdElement to reference and pass the element as a parameter to the isOverflow function. We also customize the tooltip by specifying matTooltipClass.

.tooltip {
  font-size: 1em ;
  background-color: black; 
}

Note that I need to put the above css snippet in the global (styles.scss) style class. Either that, or I need to use ::ng-deep. Otherwise, the style does not have an effect. As you may know, ::ng-deep has become deprecated, so putting the code in the global stylesheet seems like a better way.

Below screenshot shows the result:

Displaying long text using angular material tooltip

References

text-overflow – CSS: Cascading Style Sheets | MDN (mozilla.org)

white-space – CSS: Cascading Style Sheets | MDN (mozilla.org)

Determine if an HTML element’s content overflows

angular – matTooltipClass not applying css – Stack Overflow

Angular – Component styles

1 comment