This is an automated email from the ASF dual-hosted git repository. susiwen8 pushed a commit to branch codex/issue-20109-radar-tooltip-dataindex in repository https://gitbox.apache.org/repos/asf/echarts.git
commit e762e565c7982663a4e767578167503a73c0b3e1 Author: susiwen8 <[email protected]> AuthorDate: Sat May 2 21:30:40 2026 +0800 Restore radar tooltip indicator indexes for valueFormatter Radar tooltips render one name-value block per indicator, but those blocks did not carry their indicator position into the tooltip markup. Since valueFormatter receives the fragment dataIndex, the callback saw undefined for each radar indicator even though the hovered series data index was known. The fix keeps the generic tooltip pipeline unchanged and sets dataIndex on radar indicator fragments only. A unit regression covers the formatted markup callback path, and the manual HTML tooltip case makes the indicator-index behavior visible in the existing valueFormatter demo. Constraint: Existing tooltipMarkup already passes fragment.dataIndex to valueFormatter. Rejected: Change tooltipMarkup to infer array positions | would broaden behavior for all chart types and duplicate radar-specific knowledge. Confidence: high Scope-risk: narrow Directive: Keep radar indicator indexes scoped to the indicator nameValue fragments; do not replace them with the hovered series dataIndex. Tested: npx jest --config test/ut/jest.config.cjs --coverage=false test/ut/spec/component/tooltip/tooltip.test.ts Tested: npm run checktype Tested: npm run lint Not-tested: Full browser visual suite --- src/chart/radar/RadarSeries.ts | 5 +- test/tooltip-valueFormatter.html | 49 +++++++++++++++- test/ut/spec/component/tooltip/tooltip.test.ts | 77 ++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 3 deletions(-) diff --git a/src/chart/radar/RadarSeries.ts b/src/chart/radar/RadarSeries.ts index 2d2a93d5d..45d8943fa 100644 --- a/src/chart/radar/RadarSeries.ts +++ b/src/chart/radar/RadarSeries.ts @@ -115,13 +115,14 @@ class RadarSeriesModel extends SeriesModel<RadarSeriesOption> { return createTooltipMarkup('section', { header: nameToDisplay, sortBlocks: true, - blocks: zrUtil.map(indicatorAxes, axis => { + blocks: zrUtil.map(indicatorAxes, (axis, indicatorIndex) => { const val = data.get(data.mapDimension(axis.dim), dataIndex); return createTooltipMarkup('nameValue', { markerType: 'subItem', markerColor: markerColor, name: axis.name, value: val, + dataIndex: indicatorIndex, sortParam: val }); }) @@ -170,4 +171,4 @@ class RadarSeriesModel extends SeriesModel<RadarSeriesOption> { }; } -export default RadarSeriesModel; \ No newline at end of file +export default RadarSeriesModel; diff --git a/test/tooltip-valueFormatter.html b/test/tooltip-valueFormatter.html index 3d48e8e97..9e0356a16 100644 --- a/test/tooltip-valueFormatter.html +++ b/test/tooltip-valueFormatter.html @@ -41,6 +41,7 @@ under the License. <div id="main1"></div> <div id="main2"></div> <div id="main3"></div> + <div id="main4"></div> @@ -305,6 +306,52 @@ under the License. }); </script> + <script> + require(['echarts'], function (echarts) { + var option = { + animation: false, + tooltip: { + trigger: 'item', + position: 'top', + valueFormatter: function (value, dataIndex) { + return value + ' (indicatorIndex: ' + dataIndex + ')'; + } + }, + radar: { + indicator: [ + { name: 'Sales', max: 100 }, + { name: 'Administration', max: 100 }, + { name: 'Technology', max: 100 } + ] + }, + series: [ + { + type: 'radar', + data: [ + { + name: 'Allocated Budget', + value: [60, 12, 80] + } + ] + } + ] + }; + + var chart = testHelper.create(echarts, 'main4', { + title: [ + 'Radar valueFormatter should receive indicator index', + 'Expected: indicatorIndex 0, 1, 2' + ], + option: option + }); + + chart.dispatchAction({ + type: 'showTip', + dataIndex: 0, + seriesIndex: 0 + }); + }); + </script> + </body> </html> - diff --git a/test/ut/spec/component/tooltip/tooltip.test.ts b/test/ut/spec/component/tooltip/tooltip.test.ts new file mode 100644 index 000000000..ad7d0ac64 --- /dev/null +++ b/test/ut/spec/component/tooltip/tooltip.test.ts @@ -0,0 +1,77 @@ +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*/ + +import { EChartsType } from '../../../../../src/echarts'; +import { createChart, getECModel } from '../../../core/utHelper'; +import { + buildTooltipMarkup, + TooltipMarkupStyleCreator +} from '../../../../../src/component/tooltip/tooltipMarkup'; + +describe('component/tooltip', function () { + + let chart: EChartsType; + + beforeEach(function () { + chart = createChart(); + }); + + afterEach(function () { + chart.dispose(); + }); + + it('should pass radar indicator index to tooltip valueFormatter', function () { + chart.setOption({ + animation: false, + radar: { + indicator: [ + { name: 'Sales', max: 100 }, + { name: 'Administration', max: 100 }, + { name: 'Technology', max: 100 } + ] + }, + series: [{ + type: 'radar', + data: [{ + value: [60, 12, 0.8], + name: 'Allocated Budget' + }] + }] + }); + + const formatterDataIndexes: number[] = []; + const seriesModel = getECModel(chart).getSeriesByIndex(0); + const tooltipMarkup = seriesModel.formatTooltip(0, false, null) as any; + tooltipMarkup.valueFormatter = function (value: unknown, dataIndex: number): string { + formatterDataIndexes.push(dataIndex); + return value + ''; + }; + + buildTooltipMarkup( + tooltipMarkup, + new TooltipMarkupStyleCreator(), + 'html', + null, + false, + {} as any + ); + + expect(formatterDataIndexes).toEqual([0, 1, 2]); + }); +}); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
