Skip to content

Commit e37c9d1

Browse files
authored
Merge pull request #3373 from plotly/fix/layout-list-persistence
Fix layout as list and persistence
2 parents 2b47849 + 05da2c5 commit e37c9d1

File tree

3 files changed

+48
-3
lines changed

3 files changed

+48
-3
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ This project adheres to [Semantic Versioning](https://semver.org/).
1212
- [#3353](https://github.com/plotly/dash/pull/3353) Support pattern-matching/dict ids in `dcc.Loading` `target_components`
1313
- [#3371](https://github.com/plotly/dash/pull/3371) Fix allow_optional triggering a warning for not found input.
1414
- [#3379](https://github.com/plotly/dash/pull/3379) Fix dcc.Graph backward compatibility with dash 2.0 for ddk.Graph
15+
- [#3373](https://github.com/plotly/dash/pull/3373) Fix layout as list and persistence.
1516

1617
# [3.1.1] - 2025-06-29
1718

dash/dash-renderer/src/persistence.js

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,7 @@ import {createAction} from 'redux-actions';
7070

7171
import Registry from './registry';
7272
import {stringifyId} from './actions/dependencies';
73+
import {isDryComponent} from './wrapper/wrapping';
7374

7475
export const storePrefix = '_dash_persistence.';
7576

@@ -361,10 +362,11 @@ export function recordUiEdit(layout, newProps, dispatch) {
361362
* callbacks) to apply previously-stored UI edits to components
362363
*/
363364
export function applyPersistence(layout, dispatch) {
364-
if (type(layout) !== 'Object' || !layout.props) {
365-
return layout;
365+
if (Array.isArray(layout)) {
366+
return layout.map(lay =>
367+
isDryComponent(lay) ? persistenceMods(lay, lay, [], dispatch) : lay
368+
);
366369
}
367-
368370
return persistenceMods(layout, layout, [], dispatch);
369371
}
370372

tests/integration/renderer/test_persistence.py

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -560,3 +560,45 @@ def update_container2(n_clicks):
560560
# persistenceTransforms should return upper case strings
561561
dash_duo.wait_for_text_to_equal("#component-propName", "ALPACA")
562562
dash_duo.wait_for_text_to_equal("#component-propPart", "ARTICHOKE")
563+
564+
565+
def test_rdps014_layout_as_list(dash_duo):
566+
# testing persistence with layout as list
567+
app = dash.Dash(__name__)
568+
app.layout = [
569+
dcc.Input(id="input-1", value="initial", persistence=True),
570+
html.Div(id="output-1"),
571+
dcc.Input(id="input-2", value="second", persistence=True),
572+
html.Div(id="output-2"),
573+
]
574+
575+
@app.callback(Output("output-1", "children"), [Input("input-1", "value")])
576+
def update_output_1(value):
577+
return f"Output 1: {value}"
578+
579+
@app.callback(Output("output-2", "children"), [Input("input-2", "value")])
580+
def update_output_2(value):
581+
return f"Output 2: {value}"
582+
583+
dash_duo.start_server(app)
584+
585+
# Check initial values
586+
dash_duo.wait_for_text_to_equal("#output-1", "Output 1: initial")
587+
dash_duo.wait_for_text_to_equal("#output-2", "Output 2: second")
588+
589+
# Change the input values
590+
dash_duo.clear_input("#input-1")
591+
dash_duo.find_element("#input-1").send_keys("changed1")
592+
dash_duo.clear_input("#input-2")
593+
dash_duo.find_element("#input-2").send_keys("changed2")
594+
595+
# Verify changes
596+
dash_duo.wait_for_text_to_equal("#output-1", "Output 1: changed1")
597+
dash_duo.wait_for_text_to_equal("#output-2", "Output 2: changed2")
598+
599+
# Reload the page to test persistence
600+
dash_duo.wait_for_page()
601+
602+
# Check that persisted values are restored
603+
dash_duo.wait_for_text_to_equal("#output-1", "Output 1: changed1")
604+
dash_duo.wait_for_text_to_equal("#output-2", "Output 2: changed2")

0 commit comments

Comments
 (0)