Updating dcc.Location pathname
See original GitHub issueI’ve followed the updated urls example at https://plot.ly/dash/urls and have found it very helpful in setting up some rudimentary routing. I’d like to take it a bit further and allow changes made within a page to update the pathname.
From the example:
@app.callback(dash.dependencies.Output('page-content', 'children'),
[dash.dependencies.Input('url', 'pathname')])
def display_page(pathname):
return html.Div([
html.H3('You are on page {}'.format(pathname))
])
where the page-content is changed when the url pathname is updated. This works well, allowing me to set default UI states based on the pathname.
What I’d like to do is reverse the situation – UI changes update the pathname – on input from one of several internal divs, update the url pathname to reflect the current settings being used. The Link component updates the pathname, but only on click. I’d like the update to be based on graph update callbacks.
For instance (some made up pathname):
@app.callback(
Output('url', 'pathname'),
[Input('display-charts-rooms', 'children'),
Input('display-charts-room', 'children'),])
def update_pathname(graphs1,graphs2):
# outputString=get_current_settings_madeUpFunction(graphs1,graphs2)
return '/changesMade/settings=ThisAndThat'
This doesn’t seem to work however. I don’t get any errors or exceptions; but nothing happens.
With this, someone could update the the UI widgets, adjust the output graphs, all the changes could reflect in the current path name like: http://plot_server:8050/plot/dataset=1/startDate=2017-06-07/endDate=2017-06-09/
Passing this off to another user (email) would mean quick sharing of the same graph setup parameters, without having to go through tedious setup procedures (click this, wait for component to update, click next component, select multiple items from dropdown box, adjust date range 1, adjust date range 2). This seems to be inline with making dash apps more stateful, except in this case, for the user. To quote from @chriddyp on an unrelated issue:
I think that in most cases, the Dash app developer shouldn’t need to know the order of events. If they do, it usually means that the component needs to be patched in a way to make it more stateful or the UI needs to be redesigned. I’ll leave this issue open to invite examples of good UIs that are impossible to create without supporting “order-of-events”.
A downside would be the need to prevent some feedback loop: user inputs a pathname, callback takes pathname and updates page content, page content update triggers pathname change, and so on.
Other than that, I’m not knowledgeable enough with the underlying react js components to try changing them. The dcc.Location component appears simpler than other components that have update methods, but maybe I’m looking in the wrong spot:
componentWillReceiveProps(nextProps) {
this.updateLocation(nextProps);
}
render() {
return null;
As of right now, the only option I can see for easy setup/testing urls is to generate a text string as described, but output it to some P tag on screen so that a user can copy it and paste it.
Any ideas, or am I thinking about this all wrong? Thanks for any help and for the great package.
Issue Analytics
- State:
- Created 6 years ago
- Reactions:17
- Comments:17 (5 by maintainers)
Top GitHub Comments
So, I think that ideally we would allow circular relationships like this:
With support for previous state (https://github.com/plotly/dash-renderer/pull/25), we would be able to eventually do something like:
Which might make the code a little bit cleaner (easier to add more items that depend on the current path). However, we still run into the issue of having circular dependencies.
Thanks for opening @tahouse ! Yes, this would be great and you’re correct that this isn’t supported right now.
Dash doesn’t support “synced” components (there is a better name for this but I can’t recall what it is, maybe “two way bindings” would be a better way to describe it.)
In the case for URLs, we need the following flows: URL -> Updates Component Component Changes -> Updates URL
If you think about this in reactive terms like as in an Excel spreadsheet, this would cause an infinite loop - changing the URL updates the component which then updates the URL which then updates the component, etc.
What Dash should do is update the components and then stop when it detects a loop like this. Or, allow the user to configure the number of loops that it should execute before stopping (like a discrete dynamical system that eventually converges).
Then, you could write these relationships that depend on each other.
This actually comes up a lot. If we want to enable users to write and share complex models with “what if” scenarios where every parameter is configurable, then we’ll need to support this. For example, pulling from Bret Victor’s Explorable Explanations (http://worrydream.com/ExplorableExplanations/):
In that case, every word that is in the
code
syntax would be variable: you could modify any of those parameters and see the rest of the parameters update. This would require a lot of coding - for each component (you’d need to solve for the inverse relationship of that parameter and your UI would have to fix some variables in those inverse relationships), but it might be pretty cool.Long story short, I’d like to support this use case. In the meantime, I’m not aware of any other workarounds.