Closed Marc-Andre-Rivet closed 3 months ago
Also mentioned in https://github.com/plotly/dash-core/issues/197 and https://github.com/plotly/streambed/issues/15781 - this will be easy to do on the back end once the core packages are all merged into one, or we could do it in the renderer but that may take more effort (and would still require back-end tweaks to accept a list of components as the layout)
this will be easy to do on the back end once the core packages are all merged into one
I wonder what about the core packages merge would make this easier. Seems that as long as the renderer knows how to handle, visit, and render a list entry point it would be fine? Wrap it in a React Fragment
at render time.
When the packages are merged, dash
can just wrap the array in html.Div
on its own. I suppose pre-merge we could technically still do this, as dash
requires dash-html-components
, but it's inching up on a circular dependency.
We could certainly handle this in the renderer natively, but it would require a bunch of extra work to ensure paths are calculated and handled correctly - whereas the back-end change would be trivial.
@alexcjohnson I think supporting this in the renderer (not considering the BE changes as they would need to happen anyway) requires only this:
Add the following in /dash-renderer/src/index.js:
const RendererFragment = ({ children }) => (<Fragment>{children}</Fragment>)
export { RendererFragment };
Modify this section (https://github.com/plotly/dash/blob/dev/dash-renderer/src/APIController.react.js#L133-L142) of /dash-renderer/src/APIController.react.js to
if (isEmpty(layout)) {
/* Patch Layout */
const patchedLayout = Array.isArray(layoutRequest.content) ? {
namespace: 'dash_renderer',
type: 'RendererFragment',
props: {
children: layoutRequest.content
}
} : layoutRequest.content;
const finalLayout = applyPersistence(
patchedLayout,
dispatch
);
dispatch(
setPaths(computePaths(finalLayout, [], null, events.current))
);
dispatch(setLayout(finalLayout));
}
Disabling part of the BE validation and tweaking it so it accepts a list | tuple layout, this works fine:
import dash
from dash.dependencies import Input, Output
import dash_core_components as dcc
import dash_html_components as html
slider_props = dict(min=0, max=20, step=1, value=5)
app = dash.Dash(__name__)
app.layout = dcc.Slider(id='slider', **slider_props), dcc.Input(id='input'),
@app.callback(
Output('input', 'value'),
Input('slider', 'value')
)
def update(value):
return value
app.run_server(debug=True)
(screenshot after the callback was triggered)
Since we always determine at runtime the path to components, the layout
provided by the BE doesn't really matter I believe, just what gets injected into the FE layout. And here the renderer can inject its own component as need be and have no dependency on how we package things up.
In fact there's no need for
const RendererFragment = ({ children }) => (<Fragment>{children}</Fragment>)
export { RendererFragment };
hooking up directly to React.Fragment works just fine too
const patchedLayout = Array.isArray(layoutRequest.content) ? {
namespace: 'React',
type: 'Fragment',
props: {
children: layoutRequest.content
}
} : layoutRequest.content;
although it would be a bit less robust, as changes in React would be affecting us
Hi - we are tidying up stale issues and PRs in Plotly's public repositories so that we can focus on things that are most important to our community. If this issue is still a concern, please add a comment letting us know what recent version of our software you've checked it with so that I can reopen it and add it to our backlog. (Please note that we will give priority to reports that include a short reproducible example.) If you'd like to submit a PR, we'd be happy to prioritize a review, and if it's a request for tech support, please post in our community forum. Thank you - @gvwilson
Oftentimes when writing an app, a wrapper div is required. Suggesting to make the top-level wrapper optional / implicit and make the
layout
support a tuple of components.This:
Becomes: