Skip to content

fix(Tooltip): tooltip display exception when setting tooltip.valueFor…#428

Open
ader-h wants to merge 1 commit intoopentiny:devfrom
ader-h:fix-tooltip-0312
Open

fix(Tooltip): tooltip display exception when setting tooltip.valueFor…#428
ader-h wants to merge 1 commit intoopentiny:devfrom
ader-h:fix-tooltip-0312

Conversation

@ader-h
Copy link
Contributor

@ader-h ader-h commented Mar 12, 2026

…matter

Summary by CodeRabbit

  • New Features

    • Added valueFormatter option for chart tooltips, enabling direct value formatting in BarChart, LineChart, and PieChart components.
  • Refactor

    • Optimized tooltip formatting logic to prioritize direct value formatting when available.

@coderabbitai
Copy link

coderabbitai bot commented Mar 12, 2026

Walkthrough

The changes introduce support for valueFormatter as an alternative tooltip formatting approach across three chart components (BarChart, LineChart, PieChart). When provided, valueFormatter is applied directly; otherwise, the existing custom formatter logic is used. Additionally, the setDatasetSeries function signature is simplified to derive data entirely from the input options object rather than accepting external parameters.

Changes

Cohort / File(s) Summary
BarChart Series Handling
src/components/BarChart/handleSeries.js
Added conditional valueFormatter support in setLimitFormatter that bypasses legacy formatter reconstruction when a valueFormatter is supplied. Refactored setDatasetSeries signature to accept only (baseOpt, iChartOpt) instead of (baseOption, iChartOption, seriesData), deriving dataset and series directly from input options.
LineChart Tooltip Options
src/components/LineChart/handleOptipn.js
Introduced valueFormatter as an alternative formatting path that skips custom formatter construction. Adjusted formatter invocation to explicitly call coverObjDataToInit within the formatter pathway, with optional parameter slicing when isFilter is active.
PieChart Tooltip Options
src/components/PieChart/handleOptipn.js
Reworked tooltip handling to conditionally assign valueFormatter directly to baseOpt.tooltip.valueFormatter when present, otherwise falling back to wrapper formatter construction using tipHtml or tooltip.formatter.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Poem

🐰 A tooltip tale, now crisp and clean,
ValueFormatter steals the scene,
No more wrapping, just format true,
Three charts aligned in shiny new hue!
Legend flows and data beams,
Cleaner code than ever dreams!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 33.33% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly addresses the main change: adding support for tooltip.valueFormatter to fix display exceptions, which aligns with modifications across BarChart, LineChart, and PieChart components.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/components/BarChart/handleSeries.js`:
- Around line 680-687: The current branch directly assigns
iChartOption.tooltip.valueFormatter into baseOption.tooltip.valueFormatter,
bypassing setLimitFormatter's normalization (which filters 'Placeholder' series
and restores true values for % barMinHeight). Instead, keep using
setLimitFormatter(baseOption.tooltip.formatter, ...) to produce the sanitized
tooltip formatter and then wrap that result so the user-provided valueFormatter
(iChartOption.tooltip.valueFormatter) is applied to the final displayed value;
e.g., call setLimitFormatter with the existing baseOption.tooltip.formatter,
preserve exclude/barMinHeight/colors context, and compose the returned formatter
with valueFormatter so placeholders are removed and min-height-corrected values
are passed into valueFormatter before showing.

In `@src/components/LineChart/handleOptipn.js`:
- Around line 169-180: The current change replaces the existing tooltip wrapper
when valueFormatter is present, skipping the normalization/filtering logic;
instead, keep the wrapper in place (the function assigned to
baseOpt.tooltip.formatter that uses isFilter, legendData, coverObjDataToInit,
formatter, defaultFormatter) and apply tooltip?.valueFormatter within that
wrapper before returning/rendering, i.e., call the configured valueFormatter on
the normalized initParams (and pass through ticket/callback) rather than
replacing the whole formatter—ensure baseOpt.tooltip.valueFormatter is used
inside the existing formatter function so trimming helper series and converting
threshold objects still occur.

In `@src/components/PieChart/handleOptipn.js`:
- Around line 64-71: Don't short-circuit the tooltip rendering by setting
baseOpt.tooltip.valueFormatter; instead always assign baseOpt.tooltip.formatter
and inside that function build initParams (use coverObjDataToInit when params is
array), then if formatter exists call it, otherwise call defaultFormatter but
pass-through the original valueFormatter so defaultFormatter can apply custom
HTML, hideEmpty, tooltip.order and adaptive behavior; update the call site to
defaultFormatter(initParams, color, iChartOpt, baseOpt.tooltip?.hideEmpty,
baseOpt.tooltip, valueFormatter) (or update defaultFormatter's signature to
accept a valueFormatter parameter) and remove the separate
baseOpt.tooltip.valueFormatter branch so valueFormatter only affects value
formatting, not the entire renderer.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 0a2b355b-b643-42f5-a15d-d69d45a4690a

📥 Commits

Reviewing files that changed from the base of the PR and between 2d30e28 and 254bf01.

📒 Files selected for processing (3)
  • src/components/BarChart/handleSeries.js
  • src/components/LineChart/handleOptipn.js
  • src/components/PieChart/handleOptipn.js

Comment on lines +680 to +687
const valueFormatter = iChartOption.tooltip?.valueFormatter;
const toolTipFormatter = baseOption.tooltip.formatter;
const exclude = ['Placeholder'];
const colors = baseOption.color;
const barMinHeight = iChartOption.itemStyle && iChartOption.itemStyle.barMinHeight;
baseOption.tooltip.formatter = (params, ticket, callback) => {
const newParams = params.filter(item => {
return exclude.indexOf(item.seriesName) === -1;
});
// 如果设置了最小高度高度,并按%计算,将newParams值重新校正
if (barMinHeight && barMinHeight.toString().indexOf('%') !== -1) {
newParams.forEach((item) => {
if (iChartOption.data && iChartOption.data[item.dataIndex] && isNumber(iChartOption.data[item.dataIndex][item.seriesName])) {
item.data = item.value = iChartOption.data[item.dataIndex][item.seriesName]
}
})
}
if (toolTipFormatter) {
return toolTipFormatter(newParams, ticket, callback);
}
const config = {
title: '',
children: [],
hideEmpty: baseOption.tooltip?.hideEmpty
}
newParams.forEach((item, index) => {
let value = item.value || seriesData[item.seriesName][item.dataIndex];
if (isObject(item.data) && iChartOption.series) {
if (iChartOption.series[0]?.encode) {
value = item.data[item.encode.x[0]];
} else {
value = seriesData[item.seriesName] && seriesData[item.seriesName][item.dataIndex];
}
if (valueFormatter){
baseOption.tooltip.valueFormatter = valueFormatter
} else {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Preserve BarChart tooltip sanitization when valueFormatter is configured.

setLimitFormatter() is not just a formatter hook: it strips synthetic Placeholder series and restores real values when %-based barMinHeight is used. This branch bypasses that wrapper completely, so charts using tooltip.valueFormatter will surface placeholder rows and inflated min-height values in the tooltip. Please keep the filter/normalization path and apply valueFormatter to the final displayed value instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/BarChart/handleSeries.js` around lines 680 - 687, The current
branch directly assigns iChartOption.tooltip.valueFormatter into
baseOption.tooltip.valueFormatter, bypassing setLimitFormatter's normalization
(which filters 'Placeholder' series and restores true values for %
barMinHeight). Instead, keep using
setLimitFormatter(baseOption.tooltip.formatter, ...) to produce the sanitized
tooltip formatter and then wrap that result so the user-provided valueFormatter
(iChartOption.tooltip.valueFormatter) is applied to the final displayed value;
e.g., call setLimitFormatter with the existing baseOption.tooltip.formatter,
preserve exclude/barMinHeight/colors context, and compose the returned formatter
with valueFormatter so placeholders are removed and min-height-corrected values
are passed into valueFormatter before showing.

Comment on lines +169 to +180
const valueFormatter = tooltip?.valueFormatter
if (valueFormatter) {
baseOpt.tooltip.valueFormatter = valueFormatter
} else {
baseOpt.tooltip.formatter = (echartsParams, ticket, callback) => {
let params = echartsParams
if (isFilter) {
const lineNumber = legendData.length
params = echartsParams.slice(0, lineNumber)
}
const initParams = coverObjDataToInit(params)
return formatter && typeof formatter === 'function' ? formatter(initParams, ticket, callback) : defaultFormatter(initParams, color, iChartOpt, baseOpt.tooltip?.hideEmpty, baseOpt.tooltip)
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Keep the LineChart filtering/normalization wrapper even when valueFormatter is set.

This wrapper is doing more than formatting: it trims helper series for discrete/predict/filtered-area cases and converts threshold object data back to primitive values before rendering. The new early branch skips all of that, so enabling tooltip.valueFormatter will reintroduce extra series/raw object values in the tooltip and bypass the custom tooltip HTML. Please apply valueFormatter inside the existing wrapper instead of replacing it.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/LineChart/handleOptipn.js` around lines 169 - 180, The current
change replaces the existing tooltip wrapper when valueFormatter is present,
skipping the normalization/filtering logic; instead, keep the wrapper in place
(the function assigned to baseOpt.tooltip.formatter that uses isFilter,
legendData, coverObjDataToInit, formatter, defaultFormatter) and apply
tooltip?.valueFormatter within that wrapper before returning/rendering, i.e.,
call the configured valueFormatter on the normalized initParams (and pass
through ticket/callback) rather than replacing the whole formatter—ensure
baseOpt.tooltip.valueFormatter is used inside the existing formatter function so
trimming helper series and converting threshold objects still occur.

Comment on lines +64 to +71
const valueFormatter = tooltip?.valueFormatter
if (valueFormatter) {
baseOpt.tooltip.valueFormatter = valueFormatter
} else {
baseOpt.tooltip.formatter = (params, ticket, callback) => {
const initParams = isArray(params) ? coverObjDataToInit(params) : params;
return formatter && typeof formatter === 'function' ? formatter(initParams, ticket, callback) : defaultFormatter(initParams, color, iChartOpt, baseOpt.tooltip?.hideEmpty, baseOpt.tooltip)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Don't bypass PieChart's custom tooltip renderer for valueFormatter.

defaultFormatter() is also where this component applies the custom tooltip HTML, hideEmpty, tooltip.order, and adaptive/mobile behavior. This branch skips that path entirely, so setting tooltip.valueFormatter changes the whole tooltip rendering instead of only formatting the value. Please thread valueFormatter into the existing formatter/defaultFormatter flow rather than short-circuiting it here.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/components/PieChart/handleOptipn.js` around lines 64 - 71, Don't
short-circuit the tooltip rendering by setting baseOpt.tooltip.valueFormatter;
instead always assign baseOpt.tooltip.formatter and inside that function build
initParams (use coverObjDataToInit when params is array), then if formatter
exists call it, otherwise call defaultFormatter but pass-through the original
valueFormatter so defaultFormatter can apply custom HTML, hideEmpty,
tooltip.order and adaptive behavior; update the call site to
defaultFormatter(initParams, color, iChartOpt, baseOpt.tooltip?.hideEmpty,
baseOpt.tooltip, valueFormatter) (or update defaultFormatter's signature to
accept a valueFormatter parameter) and remove the separate
baseOpt.tooltip.valueFormatter branch so valueFormatter only affects value
formatting, not the entire renderer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant