[PR #21185] fix(echarts): Resolve interaction issues on charts with timelines #29588

Closed
opened 2026-02-21 20:45:51 -05:00 by yindo · 0 comments
Owner

Original Pull Request: https://github.com/langgenius/dify/pull/21185

State: closed
Merged: Yes


Fixes #20875

Summary

This PR resolves a critical issue where ECharts containing a timeline were completely non-interactive after rendering. Features like tooltips, legend toggles, and the timeline controls themselves were unresponsive.

The root cause was a combination of an overly simplistic rendering strategy and incorrect option handling for stateful charts:

  1. The chart's internal state (e.g., the current position of the timeline) was being destroyed on re-renders because notMerge={true} was used, which replaces the entire option object.
  2. The resize handling was not robust enough, leading to potential sizing issues on initial render or window resize.

This PR implements a more robust and correct rendering and interaction strategy, fully aligning with echarts-for-react best practices:

  • Correct State Management: Changed notMerge to false and added lazyUpdate={false}. This is the core fix. It allows ECharts to intelligently merge new options while preserving its internal state, which is essential for timeline interactivity.
  • Reliable Instance Handling: Implemented onChartReady to get a stable, direct reference to the ECharts instance, ensuring all operations target the correct chart.
  • Robust Resizing: Introduced a debounced resize handler and tied it to both the window.resize event and the ECharts finished event. This guarantees the chart is always correctly sized, both during interaction and after complex data rendering, while preventing performance bottlenecks.
  • Improved Component Lifecycle: Refined how the component references and state are managed throughout its lifecycle for better stability.

These changes restore full interactivity to all charts and significantly improve their rendering reliability and performance.

Important Note on Auto-Play Behavior

It is important to note that the autoPlay feature for timeline charts will only begin after the entire streaming response from the language model has completed. This is expected and correct behavior. ECharts requires the complete dataset (baseOption and all options) to initialize and run the animation. Since the chart's configuration is streamed progressively, the animation can only start once the final, complete data is received.

Test Cases & Demonstration

The following prompts were used to validate the fix across various chart types.

(I will manually attach my demonstration video and prompts below.)

My Prompts

test case prompt.txt
test case prompt tools chart.txt

Demo Video

https://github.com/user-attachments/assets/d22778fc-199a-41ec-9628-3fcc9ecc54d9

https://github.com/user-attachments/assets/73a031df-57d2-49fc-aa32-379183c13bdc

Monthly Sales Data

Checklist

  • This change requires a documentation update, included: Dify Document
  • I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!)
  • I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change.
  • [] I've updated the documentation accordingly.
  • [] I ran dev/reformat(backend) and cd web && npx lint-staged(frontend) to appease the lint gods
**Original Pull Request:** https://github.com/langgenius/dify/pull/21185 **State:** closed **Merged:** Yes --- Fixes #20875 ## Summary This PR resolves a critical issue where ECharts containing a `timeline` were completely non-interactive after rendering. Features like tooltips, legend toggles, and the timeline controls themselves were unresponsive. The root cause was a combination of an overly simplistic rendering strategy and incorrect option handling for stateful charts: 1. The chart's internal state (e.g., the current position of the timeline) was being destroyed on re-renders because `notMerge={true}` was used, which replaces the entire option object. 2. The resize handling was not robust enough, leading to potential sizing issues on initial render or window resize. This PR implements a more robust and correct rendering and interaction strategy, fully aligning with `echarts-for-react` best practices: * **Correct State Management**: Changed `notMerge` to `false` and added `lazyUpdate={false}`. This is the **core fix**. It allows ECharts to intelligently merge new options while **preserving its internal state**, which is essential for timeline interactivity. * **Reliable Instance Handling**: Implemented `onChartReady` to get a stable, direct reference to the ECharts instance, ensuring all operations target the correct chart. * **Robust Resizing**: Introduced a debounced resize handler and tied it to both the `window.resize` event and the ECharts `finished` event. This guarantees the chart is always correctly sized, both during interaction and after complex data rendering, while preventing performance bottlenecks. * **Improved Component Lifecycle**: Refined how the component references and state are managed throughout its lifecycle for better stability. These changes restore full interactivity to all charts and significantly improve their rendering reliability and performance. ### Important Note on Auto-Play Behavior It is important to note that the `autoPlay` feature for timeline charts will only begin **after** the entire streaming response from the language model has completed. This is expected and correct behavior. ECharts requires the complete dataset (`baseOption` and all `options`) to initialize and run the animation. Since the chart's configuration is streamed progressively, the animation can only start once the final, complete data is received. ## Test Cases & Demonstration The following prompts were used to validate the fix across various chart types. *(I will manually attach my demonstration video and prompts below.)* ### My Prompts [test case prompt.txt](https://github.com/user-attachments/files/20794491/test.case.prompt.txt) [test case prompt tools chart.txt](https://github.com/user-attachments/files/20794732/test.case.prompt.tools.chart.txt) ### Demo Video https://github.com/user-attachments/assets/d22778fc-199a-41ec-9628-3fcc9ecc54d9 https://github.com/user-attachments/assets/73a031df-57d2-49fc-aa32-379183c13bdc ![Monthly Sales Data](https://github.com/user-attachments/assets/f472eabb-457f-49e3-8aed-e47c6a94105e) ## Checklist - [ ] This change requires a documentation update, included: [Dify Document](https://github.com/langgenius/dify-docs) - [x] I understand that this PR may be closed in case there was no previous discussion or issues. (This doesn't apply to typos!) - [x] I've added a test for each change that was introduced, and I tried as much as possible to make a single atomic change. - [] I've updated the documentation accordingly. - [] I ran `dev/reformat`(backend) and `cd web && npx lint-staged`(frontend) to appease the lint gods
yindo added the pull-request label 2026-02-21 20:45:51 -05:00
yindo closed this issue 2026-02-21 20:45:51 -05:00
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: langgenius/dify#29588