-
-
Notifications
You must be signed in to change notification settings - Fork 145
dcc.Graph: Improve responsiveness, expose resize status, allow wrapper extension #706
Conversation
…ents into 605-graph-resize
* responsive (True) or not (False) based on the values in `config.responsive`, | ||
* `figure.layout.autosize`, `figure.layout.height`, `figure.layout.width`. | ||
*/ | ||
responsive: PropTypes.oneOf([true, false, 'auto']), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Allow users to define the behavior they want for their graph, allowing them to override the normal behavior for their config
/figure
values.
src/components/Graph.react.js
Outdated
@@ -491,6 +505,7 @@ PlotlyGraph.defaultProps = { | |||
layout: {}, | |||
frames: [], | |||
}, | |||
responsive: false, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Defaults to responsive False
which is the current behavior.
const DEFAULT_CONFIG = { | ||
responsive: true, | ||
}; | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
When responsive is true, whether through true or auto, will apply these values to config/figure to get the desired behavior.
|
||
if (type(responsive) === 'Boolean') { | ||
return responsive; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If responsive is a boolean, use as-is. Otherwise, determined auto responsiveness by looking at config/figure for the graph.
refreshOptions={{trailing: true}} | ||
refreshRate={50} | ||
onResize={this.graphResize} | ||
/> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
element resize observer - either uses ResizeObserver in newer browsers, or polyfills with a DOM/css method if it doesn't. Debounce / trail / wait to prevent making useless calls.
data-dash-is-loading={ | ||
(loading_state && loading_state.is_loading) || undefined | ||
} | ||
style={style} | ||
className={className} | ||
/> | ||
> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The graph is now wrapped in a div
that applies the styling -- the graph div itself has consistent styling. This appears to help responsiveness to work correctly in flex flows.
- Need to make sure this is truly useful, not development side-effects.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm still concerned about adding js-plotly-plot
to the outer div - seems like having two nested divs with this class could lead to strange behavior, if it's actually getting used for something in CSS. Can you explain the reasoning here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Understandable. My goal here is for old versions of DDK to continue having the same behavior. Given the way DDK styling works and the stated goal of minimizing custom CSS, this should be fine. To break this behavior would require users to assign display: flex;
to js-plotly-plot
. The next DDK release will be using .dash-graph
.
For the DCC world, this is probably a non-issue, the general idea is that we support classes & attributes with the dash-
prefix, everything else is implementation details.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we don't add js-plotly-plot
, dash>=1.8.0
will be a breaking version.
If we do add it, we can always create an issue to remove it and tag that issue as Dash v2.x
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As pointed out by @alexcjohnson, in the end the legacy
js-plotly-plot
is not necessary as old ddk uses the forked version of the graph anyway.
Discussing this with @wbrgss, it seems like the only scenario left is a new version of DDK pointing to an old version of Dash, but that can be handled through CSS with *:not(.dash-graph) > .js-plotly-js
in DDK itself.
I would recommend adding |
- add className to fallback impl
- shared div key between the fallback and real graph
…ents into 605-graph-resize
01a5e49
to
530ef65
Compare
Apart from waiting for the release from Plotly.js, the last remaining contention point might be the use of |
- rework plotly.min.js inclusion and update logic
.gitignore
Outdated
@@ -17,6 +17,7 @@ venv/ | |||
|
|||
/build | |||
/dash_core_components | |||
/dash_core_components_base/plotly.min.js |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cleaned up generation a bit to copy file directly from node_modules instead of keeping a to-be-synced copy in the py generation base folder
### Updated | ||
- [#706](https://github.com/plotly/dash-core-components/pull/706) | ||
- Upgraded plotly.js to [1.51.3](https://github.com/plotly/plotly.js/releases/tag/v1.51.3) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plotly.js 1.51.3 with the promise fix 🎉
2. Run `npm install` followed by `npm run build`, this will ensure the latest version of Plotly.js is in `node_modules` and copy | ||
that version over with the other build artifacts | ||
3. Update `dash_core_components_base/__init__.py` plotly.js `relative_package_path` and `external_url` | ||
2. Run `npm install` followed by `npm run build`, the Plotly.js artifact will be copied and bundled over as required |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Plotly.js artifact is now always plotly.min.js
, no need for weird updates
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks clean clean clean 😉
Nice build simplifications, thanks!
💃
); | ||
}); | ||
|
||
ControlledPlotlyGraph.propTypes = PropTypes.any; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@Marc-Andre-Rivet I'm seeing a funny warning message in debug mode:
The prop `isRequired` is marked as required in `<<anonymous>>`,
but its value is `undefined`
That I think is coming from here... Should this just be a copy of PlotlyGraph.propTypes
perhaps?
@Marc-Andre-Rivet -- Apologies for the thread dig. Re: the side-effect of this PR... it also breaks the ability for end users to modify the contained plotly figure using clientside callbacks. Why? Client-side "UI" changes are much faster and provides a better user experience for things like changing axis on ranges, updating titles, etc. Specifically, I've been using a this approach to trigger relayout via This problem is resolved by shifting the component's However, running the full test suite, I get some flaky results (only passes on first run) due to parameterized |
Fixes #605
Context
(1) Graph resize
Plotly.js provides graph resize on
window.resize
event but does not provide graph resize on parent element resize. This is consistent with other similar libraries.Graph resize is affected by many props on the graph figure and config, namely:
figure.layout.autosize
,figure.layout.height
,figure.layout.width
config.responsive
The overall behavior is complex and can be summarized by these checks:
https://github.com/plotly/dash-core-components/blob/605-graph-resize/tests/integration/graph/test_graph_responsive.py#L101
https://github.com/plotly/dash-core-components/blob/605-graph-resize/tests/integration/graph/test_graph_responsive.py#L107
(2) Extendable figure/config processing in wrapped component
In certain use cases, the dcc.Graph is wrapped inside another component and provides a service rather than being the desired component itself. In these situations the wrapper component may want to override the graph's figure/config processing with logic of its own.
(3) Graph resizing / loading / asyncing... not ready in general
In certain use cases, the application requires the dcc.Graph to be fully loaded, renderered, and resized before some other operation is made (e.g. QA / testing).
Proposed Changes
responsive
that will override the graph responsiveness.responsive
allows 3 values: True, False, 'auto' (default) that will (True) force the graph to be responsive, (False) force the graph to be non-responsive, ('auto') use the graph's default behavior and make the graph responsive on parent resize if applicablefunction
props:_dashprivate_transformFigure
and_dashprivate_transformConfig
that will override default processing offigure
andconfig
(https://github.com/plotly/dash-core-components/blob/605-graph-resize/src/fragments/Graph.react.js#L142)_dashprivate_transformFigure
or_dashprivate_transformConfig
is updated (e.g. generate a new function when the params change)dash-graph--pending
class to the wrapper div of the component** Changed unrelated to responsiveness **
Side-effects
dash-graph
, havejs-plotly-plot
, the class added by Plotly.js on graph divs.Dependencies and other considerations
Todo
dash-graph-pending
flag / class -- need to validate the class gets added prior to theresize
starting, there might be a need for deferringresize
inside asetTimeout(..., 0)
flex
into hard-coded heights and percentages, the graphs are responsive and all.v1.8
alsoUse variation of https://github.com/plotly/dash-core-components/blob/605-graph-resize/tests/integration/graph/test_graph_responsive.py#L23 to manually test scenarios.