diff --git a/packages/reflex-components-plotly/news/6977.bugfix.md b/packages/reflex-components-plotly/news/6977.bugfix.md new file mode 100644 index 00000000000..bdc3081d7f8 --- /dev/null +++ b/packages/reflex-components-plotly/news/6977.bugfix.md @@ -0,0 +1 @@ +`rx.plotly(..., id="...")` now reaches the DOM: the `id` prop is rendered as react-plotly.js's `divId`, which is the only id prop the library forwards to its container div. diff --git a/packages/reflex-components-plotly/src/reflex_components_plotly/plotly.py b/packages/reflex-components-plotly/src/reflex_components_plotly/plotly.py index b5297e14b48..34e1f3ec47c 100644 --- a/packages/reflex-components-plotly/src/reflex_components_plotly/plotly.py +++ b/packages/reflex-components-plotly/src/reflex_components_plotly/plotly.py @@ -70,6 +70,10 @@ class Point(TypedDict): bbox: BBox | None +_ID_PROP = "id" +_DIV_ID_PROP = "divId" + + class Plotly(NoSSRComponent): """Display a plotly graph.""" @@ -308,6 +312,12 @@ def _exclude_props(self) -> set[str]: def _render(self): tag = super()._render() + # react-plotly.js only forwards `divId` (plus style, className and ref) to + # the container div it renders; the framework `id` prop would be dropped. + element_id = tag.props.get(_ID_PROP) + if element_id is not None: + tag = tag.remove_props(_ID_PROP) + tag = tag.set(props={**tag.props, _DIV_ID_PROP: element_id}) figure = self.data.to(dict) if self.data is not None else Var.create({}) merge_dicts = [] # Data will be merged and spread from these dict Vars if self.layout is not None: diff --git a/pyi_hashes.json b/pyi_hashes.json index 603fc724e48..5241bf7cba4 100644 --- a/pyi_hashes.json +++ b/pyi_hashes.json @@ -42,7 +42,7 @@ "packages/reflex-components-lucide/src/reflex_components_lucide/icon.pyi": "1e331a3d6420b97e5b1ce7f63ad53de8", "packages/reflex-components-markdown/src/reflex_components_markdown/markdown.pyi": "79d0a59b1ba12a2f2c4a09fa6b5c776f", "packages/reflex-components-moment/src/reflex_components_moment/moment.pyi": "13e39f8d2b46bfd76c50cb04062da8ff", - "packages/reflex-components-plotly/src/reflex_components_plotly/plotly.pyi": "beb057e382e527224597c320dbb72385", + "packages/reflex-components-plotly/src/reflex_components_plotly/plotly.pyi": "f411341e59a3065fee964747584f9fcf", "packages/reflex-components-radix/src/reflex_components_radix/__init__.pyi": "a77352f60fb6f4135b5d08a6e56efa6d", "packages/reflex-components-radix/src/reflex_components_radix/primitives/__init__.pyi": "bbd4d1a4fa73275a882c33ba485d0165", "packages/reflex-components-radix/src/reflex_components_radix/primitives/accordion.pyi": "2639b56ce9ccb8b404c6dc12eaace19d", diff --git a/tests/units/components/graphing/test_plotly.py b/tests/units/components/graphing/test_plotly.py index 85dcb2da646..bfb53a2ec55 100644 --- a/tests/units/components/graphing/test_plotly.py +++ b/tests/units/components/graphing/test_plotly.py @@ -75,3 +75,26 @@ def test_plotly_basic_locale_option_merges_into_config(plotly_fig: go.Figure): assert "locale" not in rendered.props assert "_rxGetPlotlyLocaleConfig" in str(config_var) assert "fr" in str(config_var) + + +def test_plotly_id_renders_as_div_id(plotly_fig: go.Figure): + """Test that `id` reaches the DOM via react-plotly.js's `divId` prop. + + Args: + plotly_fig: The figure to display. + """ + rendered = rx.plotly(data=plotly_fig, id="the-plot")._render() + + assert "id" not in rendered.props + assert "the-plot" in str(rendered.props["divId"]) + + +def test_plotly_without_id_has_no_div_id(plotly_fig: go.Figure): + """Test that no `divId` is emitted when no `id` was given. + + Args: + plotly_fig: The figure to display. + """ + rendered = rx.plotly(data=plotly_fig)._render() + + assert "divId" not in rendered.props