Display Axis Labels Tooltip

The Chart does not provide a built-in Tooltip for the Axis labels. To display a custom tooltip when hovering the Chart axis labels, bind to the mouseenter and mouseleave events of the Chart's surface element, and toggle a Popup with dynamic content based on the hovered label.

The popup could display a shortened version of the text or a different text entirely. The content is transferred to the axis label visual, a low-level drawing element, and displayed when its hovered.

The following example demonstrates the described approach:

import { Component, TemplateRef, ViewChild } from '@angular/core';
import { AxisLabelVisualArgs } from '@progress/kendo-angular-charts';
import { PopupRef, PopupService } from '@progress/kendo-angular-popup';

@Component({
    selector: 'my-app',
    template: `
      <kendo-chart (render)="attachSurfaceHandlers($event)">
        <kendo-chart-title text='Custom axis tooltips'></kendo-chart-title>
        <kendo-chart-legend [visible]='false'></kendo-chart-legend>
        <kendo-chart-category-axis>
          <kendo-chart-category-axis-item>
            <kendo-chart-category-axis-item-labels [visual]='visual'>
            </kendo-chart-category-axis-item-labels>
          </kendo-chart-category-axis-item>
        </kendo-chart-category-axis>
        <kendo-chart-series>
          <kendo-chart-series-item type='bar' [data]='data' field="value" categoryField='name'>
          </kendo-chart-series-item>
        </kendo-chart-series>
      </kendo-chart>

      <ng-template #popupTemplate>
        <div class="chart-popup k-tooltip">
          {{ popupContent }}
        </div>
      </ng-template>
    `,
    styles: [`
      .chart-popup {
        width: max-content;
        max-width: 300px;
      }
    `]
})
export class AppComponent {
  public data: any[] = [{
    name: 'Zero',
    // No description
    value: 0
  }, {
    name: 'One',
    description: 'The natural number after zero',
    value: 1
  }, {
    name: 'π',
    description: 'The constant representing the ratio of a circle`s circumference to its diameter, approximately equal to 3.141592653589793238462643',
    value: Math.PI
  }, {
    name: '√2',
    description: 'The length of the diagonal of a square with unit sides, approximately equal to 1.414213562373095048801688',
    value: Math.SQRT2
  }, {
    name: 'φ',
    description: 'Golden ratio, approximately equal to 1.618033988749894848204586',
    value: 1.618033988749894848204586
  }];

  @ViewChild('popupTemplate', { static: true })
  public popupTemplate: TemplateRef<any>;
  public popupContent: string;

  private popupRef: PopupRef;

  constructor(private popupService: PopupService) {}

  public attachSurfaceHandlers(e: any): void {
    // Note that surface event handlers run outside the Angular Zone.
    // You may need to use NgZone.run to trigger change detection.
    e.sender.surface.bind('mouseenter', args => this.onMouseEnter(args));
    e.sender.surface.bind('mouseleave', args => this.onMouseLeave(args));

    // Surface event handlers will be cleared automatically when the chart is destroyed.
  }

  public onMouseEnter(e: any): void {
    const tooltip = e.element.parent.tooltip;
    if (!tooltip) {
      return;
    }

    if (this.popupRef) {
      this.popupRef.close();
    }

    this.popupContent = tooltip;
    this.popupRef = this.popupService.open({
      content: this.popupTemplate,
      offset: {
        left: e.originalEvent.pageX + 10,
        top: e.originalEvent.pageY + 10
      }
    });
  }

  public onMouseLeave(): void {
    if (!this.popupRef) {
      return;
    }

    this.popupRef.close();
    this.popupRef = null;
  }

  // Please note that visual is an arrow function in order to capture `this`.
  public visual = (e: AxisLabelVisualArgs): any => {
    // Create the default label visual
    const visual = e.createVisual();

    // Set the text on a custom `tooltip` field.
    (<any> visual).tooltip = e.dataItem.description;

    return visual;
  }
}
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ChartsModule } from '@progress/kendo-angular-charts';
import { PopupModule } from '@progress/kendo-angular-popup';
import { HttpClientModule } from '@angular/common/http';

import 'hammerjs';

import { AppComponent } from './app.component';

@NgModule({
  imports: [ BrowserModule, BrowserAnimationsModule, ChartsModule, FormsModule, HttpClientModule, PopupModule ],
  declarations: [ AppComponent ],
  bootstrap: [ AppComponent ]
})

export class AppModule { }
import { enableProdMode } from '@angular/core';
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';

import { ChartsModule } from '@progress/kendo-angular-charts';
import { AppModule } from './app.module';

enableProdMode();

const platform = platformBrowserDynamic();
platform.bootstrapModule(AppModule);

In this article