Every chart shows a tooltip when a data point is hovered. By default it is the point's key and value. Project an <ng-template pcacTooltip> into a chart and that template is rendered instead — a real Angular template with the hovered data bound into it, so pipes, control flow, your own components and styles all work as they would anywhere else.
Hover the charts below. Each one has its own template; the bar and line tooltips use parent to show the point's share of its group / series, and the bar chart's thresholds are flagged via isThreshold.
parent is the group
parent is the series
No parent: slices are top level
Import PcacTooltipDirective alongside the chart component, then put an <ng-template pcacTooltip> inside the chart element. The hovered datum is the template's implicit value (let-point, or whatever name you like); the rest of the context is picked up by name.
import { PcacBarVerticalChart, PcacTooltipDirective } from '@pioneer-code/pioneer-charts';
@Component({
imports: [PcacBarVerticalChart, PcacTooltipDirective],
// ...
})<!-- Project an <ng-template pcacTooltip> into any chart. -->
<pcac-bar-vertical-chart [config]="config">
<ng-template pcacTooltip let-point let-group="parent" let-threshold="isThreshold">
<div class="my-tooltip">
<strong>{{ group?.key }}</strong>
<span>{{ point.key }}: {{ point.value | number }}</span>
@if (threshold) {
<em>threshold</em>
}
</div>
</ng-template>
</pcac-bar-vertical-chart>The template is type-checked against PcacTooltipContext under strictTemplates, so point.value and friends are checked as PcacData.
interface PcacTooltipContext {
// The hovered datum: a bar, a line/area/plot point, a pie slice, or a threshold.
$implicit: PcacData;
// What it sits inside: the group a bar belongs to, the series a point belongs to, or for a
// threshold the data group it's drawn against. null when there is no enclosing level
// (pie slices, a chart-wide threshold).
parent: PcacData | null;
// True when a bar chart threshold marker is hovered rather than a data point.
isThreshold: boolean;
// Position of the hovered datum in parent.data (or in the top-level data when there is no
// parent, e.g. a pie slice). For a threshold, its position in thresholds.
index: number;
// Position of parent in the top-level data; null whenever parent is.
parentIndex: number | null;
// Every *other* datum drawn at exactly the same coordinate as the hovered one, in data order,
// each located the same way ({ data, parent, index, parentIndex }). Set by the line, area and
// plot charts - whether or not the plot chart's pointFanOut has spread them apart - and empty
// on the other charts and whenever nothing shares the point.
coincident: PcacTooltipCoincident[];
}A PcacData only carries a key and a value, but the tooltip often wants more — the customer behind an order, the unit a reading was taken in. The context's index and parentIndex give the hovered datum's position in data, and charts never reorder data, so if the collection you built it from is parallel (same order, nothing filtered out) those two indexes reach straight back into it:
// Your source collection, grouped the same way the chart is: one entry per group,
// one item per bar. Build the chart's data from it without reordering or filtering.
regions: Region[] = [
{ name: 'North', orders: [{ customer: 'Acme', total: 1200 }, { customer: 'Globex', total: 800 }] },
{ name: 'South', orders: [{ customer: 'Initech', total: 950 }] },
];
config: PcacBarVerticalChartConfig = {
...new PcacBarVerticalChartConfig(),
data: this.regions.map(region => ({
key: region.name, value: null, hide: false,
data: region.orders.map(order => ({ key: order.customer, value: order.total, hide: false, data: [] })),
})),
};<!-- parentIndex picks the region, index picks the order within it. -->
<pcac-bar-vertical-chart [config]="config">
<ng-template pcacTooltip let-point let-i="index" let-g="parentIndex">
@let order = regions[g!].orders[i];
<div class="my-tooltip">
<strong>{{ order.customer }}</strong>
<span>{{ order.total | currency }}</span>
</div>
</ng-template>
</pcac-bar-vertical-chart>parentIndex is null when there is no enclosing level (a pie slice, or a chart-wide threshold), so for a pie use items[index] directly. For a threshold, index is its position in thresholds (or in thresholds[parentIndex].data for a per-bar threshold). If your collection isn't parallel to data — you filter, sort or group on the way in — look the item up by key instead, or keep a map from key to item; a positional link would silently point at the wrong row.
With a template present the library applies none of its own tooltip styling — no background, padding, font or color. It only positions the rendered template (centered above the cursor) and keeps it from intercepting the mouse. The template owns the whole box.
/* The template owns the whole box; give it whatever look you want. */
.my-tooltip {
padding: 0.5rem 0.75rem;
border-radius: 6px;
background: #fff;
box-shadow: 0 4px 16px rgba(0, 0, 0, 0.15);
white-space: nowrap;
}The tooltip is rendered into <body> so it can float over anything, but its nodes are still stamped with your component's style scope, so component styles like the one above reach it without ::ng-deep or global CSS.
xAxis.format / yAxis.format as before; those formats are not applied to a custom template, which gets the raw PcacData. pcacTooltip template inside a chart element is used.