Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[charts] Add dataIndex to series valueFormatter #12745

6 changes: 3 additions & 3 deletions docs/data/charts/tooltip/Formatting.js
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ export default function Formatting() {
<LineChart
{...lineChartsParams}
xAxis={[{ data: years, scaleType: 'time', valueFormatter: yearFormatter }]}
series={lineChartsParams.series.map((serie) => ({
...serie,
valueFormatter: currencyFormatter,
series={lineChartsParams.series.map((series) => ({
...series,
valueFormatter: (v) => (v === null ? '' : currencyFormatter(v)),
}))}
/>
);
Expand Down
6 changes: 3 additions & 3 deletions docs/data/charts/tooltip/Formatting.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -87,9 +87,9 @@ export default function Formatting() {
<LineChart
{...lineChartsParams}
xAxis={[{ data: years, scaleType: 'time', valueFormatter: yearFormatter }]}
series={lineChartsParams.series.map((serie) => ({
...serie,
valueFormatter: currencyFormatter,
series={lineChartsParams.series.map((series) => ({
...series,
valueFormatter: (v) => (v === null ? '' : currencyFormatter(v)),
}))}
/>
);
Expand Down
6 changes: 3 additions & 3 deletions docs/data/charts/tooltip/Formatting.tsx.preview
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
<LineChart
{...lineChartsParams}
xAxis={[{ data: years, scaleType: 'time', valueFormatter: yearFormatter }]}
series={lineChartsParams.series.map((serie) => ({
...serie,
valueFormatter: currencyFormatter,
series={lineChartsParams.series.map((series) => ({
...series,
valueFormatter: (v) => (v === null ? '' : currencyFormatter(v)),
}))}
/>
38 changes: 38 additions & 0 deletions docs/data/charts/tooltip/SeriesFormatter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as React from 'react';
import { PieChart } from '@mui/x-charts/PieChart';
import { legendClasses } from '@mui/x-charts';

const otherProps = {
width: 400,
height: 200,
sx: {
[`.${legendClasses.root}`]: {
transform: 'translate(20px, 0)',
},
},
};

const data = [
{ team: 'Amber Ants', rank: 3, points: 31 },
{ team: 'Eagle Warriors', rank: 1, points: 50 },
{ team: 'Elephant Trunk', rank: 4, points: 18 },
{ team: 'Jaguars', rank: 2, points: 37 },
{ team: 'Smooth Pandas', rank: 5, points: 6 },
];

export default function SeriesFormatter() {
return (
<PieChart
series={[
{
data: data.map((d) => ({ label: d.team, id: d.team, value: d.points })),
valueFormatter: (v, { dataIndex }) => {
const { rank } = data[dataIndex];
return `has ${v.value} points and is ranked ${rank}.`;
},
},
]}
{...otherProps}
/>
);
}
38 changes: 38 additions & 0 deletions docs/data/charts/tooltip/SeriesFormatter.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import * as React from 'react';
import { PieChart, PieChartProps } from '@mui/x-charts/PieChart';
import { legendClasses } from '@mui/x-charts';

const otherProps: Partial<PieChartProps> = {
width: 400,
height: 200,
sx: {
[`.${legendClasses.root}`]: {
transform: 'translate(20px, 0)',
},
},
};

const data = [
{ team: 'Amber Ants', rank: 3, points: 31 },
{ team: 'Eagle Warriors', rank: 1, points: 50 },
{ team: 'Elephant Trunk', rank: 4, points: 18 },
{ team: 'Jaguars', rank: 2, points: 37 },
{ team: 'Smooth Pandas', rank: 5, points: 6 },
];

export default function SeriesFormatter() {
return (
<PieChart
series={[
{
data: data.map((d) => ({ label: d.team, id: d.team, value: d.points })),
valueFormatter: (v, { dataIndex }) => {
const { rank } = data[dataIndex];
return `has ${v.value} points and is ranked ${rank}.`;
},
},
]}
{...otherProps}
/>
);
}
12 changes: 12 additions & 0 deletions docs/data/charts/tooltip/SeriesFormatter.tsx.preview
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<PieChart
series={[
{
data: data.map((d) => ({ label: d.team, id: d.team, value: d.points })),
valueFormatter: (v, { dataIndex }) => {
const { rank } = data[dataIndex];
return `has ${v.value} points and is ranked ${rank}.`;
},
},
]}
{...otherProps}
/>
8 changes: 8 additions & 0 deletions docs/data/charts/tooltip/tooltip.md
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,14 @@ Here is a demo with:

{{"demo": "Formatting.js"}}

### Advanced formatting

The series `valueFormatter` provides a context as its second argument containing a `dataIndex` property which you can use to calculate other data-related values.

In the demo below you can notice we use `dataIndex` to add each team's rank in the tooltip.

{{"demo": "SeriesFormatter.js"}}

### Axis formatter

To modify how data is displayed in the axis use the `valueFormatter` property.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ function DefaultChartsAxisTooltipContent(props: ChartsAxisContentProps) {
.filter(isCartesianSeries)
.map(({ color, id, label, valueFormatter, data, getColor }) => {
// @ts-ignore
const formattedValue = valueFormatter(data[dataIndex] ?? null);
const formattedValue = valueFormatter(data[dataIndex] ?? null, { dataIndex });
if (formattedValue == null) {
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ function DefaultChartsItemTooltipContent<T extends ChartSeriesType = ChartSeries
const value = series.data[itemData.dataIndex];
const formattedValue = (
series.valueFormatter as CommonSeriesType<typeof value>['valueFormatter']
)?.(value);
)?.(value, { dataIndex: itemData.dataIndex });
return (
<ChartsTooltipPaper sx={sx} className={classes.root}>
<ChartsTooltipTable className={classes.table}>
Expand Down
6 changes: 4 additions & 2 deletions packages/x-charts/src/PieChart/formatter.ts
Original file line number Diff line number Diff line change
Expand Up @@ -40,9 +40,11 @@ const formatter: Formatter<'pie'> = (params) => {
id: item.id ?? `auto-generated-pie-id-${seriesId}-${index}`,
...arcs[index],
}))
.map((item) => ({
.map((item, index) => ({
...item,
formattedValue: series[seriesId].valueFormatter?.(item) ?? item.value.toLocaleString(),
formattedValue:
series[seriesId].valueFormatter?.(item, { dataIndex: index }) ??
item.value.toLocaleString(),
})),
};
});
Expand Down
15 changes: 9 additions & 6 deletions packages/x-charts/src/internals/defaultizeValueFormatter.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import { SeriesId } from '../models/seriesType/common';
import { SeriesId, SeriesValueFormatter } from '../models/seriesType/common';

function defaultizeValueFormatter<
ISeries extends { valueFormatter?: IFormatter },
IFormatter extends (v: any) => string,
TValue,
ISeries extends { valueFormatter?: SeriesValueFormatter<TValue> },
>(
series: Record<SeriesId, ISeries>,
defaultValueFormatter: IFormatter,
): Record<SeriesId, ISeries & { valueFormatter: IFormatter }> {
const defaultizedSeries: Record<SeriesId, ISeries & { valueFormatter: IFormatter }> = {};
defaultValueFormatter: SeriesValueFormatter<TValue>,
): Record<SeriesId, ISeries & { valueFormatter: SeriesValueFormatter<TValue> }> {
const defaultizedSeries: Record<
SeriesId,
ISeries & { valueFormatter: SeriesValueFormatter<TValue> }
> = {};
Object.keys(series).forEach((seriesId) => {
defaultizedSeries[seriesId] = {
...series[seriesId],
Expand Down
5 changes: 5 additions & 0 deletions packages/x-charts/src/models/axis.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,11 @@ interface AxisScaleComputedConfig {
};
}
export type AxisValueFormatterContext = {
/**
* Location indicates where the value will be displayed.
* - `'tick'` The value is displayed on the axis ticks.
* - `'tooltip'` The value is displayed in the tooltip when hovering the chart.
*/
location: 'tick' | 'tooltip';
JCQuintas marked this conversation as resolved.
Show resolved Hide resolved
};

Expand Down
17 changes: 15 additions & 2 deletions packages/x-charts/src/models/seriesType/common.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,28 @@ import type { StackOffsetType, StackOrderType } from '../stacking';

export type SeriesId = number | string;

export type SeriesValueFormatterContext = {
/**
* The index of the value in the data array.
*/
dataIndex: number;
};

export type SeriesValueFormatter<TValue> = (
value: TValue,
context: SeriesValueFormatterContext,
) => string;

export type CommonSeriesType<TValue> = {
id?: SeriesId;
color?: string;
/**
* Formatter used to render values in tooltip or other data display.
* @param {TValue} value The series' value to render.
* @returns {string} The string to dispaly.
* @param {SeriesValueFormatterContext} context The rendering context of the value.
* @returns {string} The string to display.
*/
valueFormatter?: <Value extends TValue>(value: Value) => string;
valueFormatter?: SeriesValueFormatter<TValue>;
highlightScope?: Partial<HighlightScope>;
};

Expand Down