Skip to content

Commit

Permalink
Merge pull request #2152 from plotly/fix-component-as-prop
Browse files Browse the repository at this point in the history
Fix component as prop with multiple components in list of objects
  • Loading branch information
T4rk1n authored Aug 12, 2022
2 parents b569dfe + f68acab commit 20b6467
Show file tree
Hide file tree
Showing 4 changed files with 96 additions and 67 deletions.
11 changes: 10 additions & 1 deletion @plotly/dash-test-components/src/components/ComponentAsProp.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,14 @@ import PropTypes from 'prop-types';


const ComponentAsProp = (props) => {
const { element, id, shapeEl, list_of_shapes } = props;
const { element, id, shapeEl, list_of_shapes, multi_components } = props;
return (
<div id={id}>
{shapeEl && shapeEl.header}
{element}
{shapeEl && shapeEl.footer}
{list_of_shapes && <ul>{list_of_shapes.map(e => <li key={e.value}>{e.label}</li>)}</ul> }
{multi_components && <div>{multi_components.map(m => <div id={m.id} key={m.id}>{m.first} - {m.second}</div>)}</div>}
</div>
)
}
Expand All @@ -28,6 +29,14 @@ ComponentAsProp.propTypes = {
label: PropTypes.node,
value: PropTypes.number,
})
),

multi_components: PropTypes.arrayOf(
PropTypes.exact({
id: PropTypes.string,
first: PropTypes.node,
second: PropTypes.node,
})
)
}

Expand Down
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@
All notable changes to `dash` will be documented in this file.
This project adheres to [Semantic Versioning](https://semver.org/).

## [UNRELEASED]

### Fixed

- [#2152](https://github.com/plotly/dash/pull/2152) Fix bug [#2128](https://github.com/plotly/dash/issues/2128) preventing rendering of multiple components inside a dictionary.

## [2.6.1] - 2022-08-01

### Fixed
Expand Down
126 changes: 61 additions & 65 deletions dash/dash-renderer/src/TreeContainer.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import {
mergeRight,
pick,
pickBy,
pipe,
propOr,
path as rpath,
pathOr,
Expand Down Expand Up @@ -246,76 +245,73 @@ class BaseTreeContainer extends Component {
],
_dashprivate_config
);
const props = pipe(
dissoc('children'),
...childrenProps
.map(childrenProp => {
if (childrenProp.includes('.')) {
let path = childrenProp.split('.');
let node;
let nodeValue;
if (childrenProp.includes('[]')) {
let frontPath = [],
backPath = [],
found = false;
path.forEach(p => {
if (!found) {
if (p.includes('[]')) {
found = true;
frontPath.push(p.replace('[]', ''));
} else {
frontPath.push(p);
}
} else {
backPath.push(p);
}
});

node = rpath(frontPath, _dashprivate_layout.props);
if (node === undefined) {
return;
let props = dissoc('children', _dashprivate_layout.props);

for (let i = 0; i < childrenProps.length; i++) {
const childrenProp = childrenProps[i];
if (childrenProp.includes('.')) {
let path = childrenProp.split('.');
let node;
let nodeValue;
if (childrenProp.includes('[]')) {
let frontPath = [],
backPath = [],
found = false;
path.forEach(p => {
if (!found) {
if (p.includes('[]')) {
found = true;
frontPath.push(p.replace('[]', ''));
} else {
frontPath.push(p);
}
if (!node.length) {
return assocPath(frontPath, node);
}
const firstNode = rpath(backPath, node[0]);
if (!firstNode) {
return assocPath(frontPath, node);
}
nodeValue = node.map((element, i) => {
const elementPath = concat(
frontPath,
concat([i], backPath)
);
return assocPath(
backPath,
this.wrapChildrenProp(
rpath(backPath, element),
elementPath
),
element
);
});
path = frontPath;
} else {
node = rpath(path, _dashprivate_layout.props);
if (node === undefined) {
return;
}
nodeValue = this.wrapChildrenProp(node, path);
backPath.push(p);
}
return assocPath(path, nodeValue);
});

node = rpath(frontPath, props);
if (node === undefined || !node.length) {
continue;
}
const firstNode = rpath(backPath, node[0]);
if (!firstNode) {
continue;
}
const node = _dashprivate_layout.props[childrenProp];
if (node !== undefined) {
return assoc(
childrenProp,
this.wrapChildrenProp(node, [childrenProp])
nodeValue = node.map((element, i) => {
const elementPath = concat(
frontPath,
concat([i], backPath)
);
return assocPath(
backPath,
this.wrapChildrenProp(
rpath(backPath, element),
elementPath
),
element
);
});
path = frontPath;
} else {
node = rpath(path, props);
if (node === undefined) {
continue;
}
})
.filter(e => e !== undefined)
)(_dashprivate_layout.props);
nodeValue = this.wrapChildrenProp(node, path);
}
props = assocPath(path, nodeValue, props);
continue;
}
const node = props[childrenProp];
if (node !== undefined) {
props = assoc(
childrenProp,
this.wrapChildrenProp(node, [childrenProp]),
props
);
}
}

if (type(props.id) === 'Object') {
// Turn object ids (for wildcards) into unique strings.
Expand Down
20 changes: 19 additions & 1 deletion tests/integration/renderer/test_component_as_prop.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from dash import Dash, Input, Output, callback_context

from dash_test_components import ComponentAsProp
from dash.html import Button, Div
from dash.html import Button, Div, Span


def test_rdcap001_component_as_prop(dash_duo):
Expand Down Expand Up @@ -90,6 +90,21 @@ def test_rdcap001_component_as_prop(dash_duo):
]
},
),
ComponentAsProp(
id="multi-component",
multi_components=[
{
"id": "multi",
"first": Span("first"),
"second": Span("second"),
},
{
"id": "multi2",
"first": Span("foo"),
"second": Span("bar"),
}
],
),
]
)

Expand Down Expand Up @@ -187,4 +202,7 @@ def updated_from_list(*_):
dash_duo.wait_for_text_to_equal("#first-in-shape", "one")
dash_duo.wait_for_text_to_equal("#second-in-shape", "two")

dash_duo.wait_for_text_to_equal("#multi", "first - second")
dash_duo.wait_for_text_to_equal("#multi2", "foo - bar")

assert dash_duo.get_logs() == []

0 comments on commit 20b6467

Please sign in to comment.