question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Updating dcc.Location pathname

See original GitHub issue

I’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:open
  • Created 6 years ago
  • Reactions:17
  • Comments:17 (5 by maintainers)

github_iconTop GitHub Comments

6reactions
chriddypcommented, Nov 6, 2017

So, I think that ideally we would allow circular relationships like this:

# clicking on radio item updates the URL
@app.callback(Output('location', 'pathname'), [Input('radio', 'value')])
def update_pathname(value):
     return '/{}'.format(value)

# landing on a page directly updates the radio item navigator
@app.callback(Output('radio', 'value'), [Input('location', 'pathname')])
def sync_pathname(value):
     return value.strip('/')

With support for previous state (https://github.com/plotly/dash-renderer/pull/25), we would be able to eventually do something like:

@app.callback(
    Output('store', 'children'),
    [Input('radio', 'value'), Input('location', 'pathname')],
    [PrevState('radio', 'value'), PrevState('location', 'pathname')])
def update_current_location(radio, path, prevRadio, prevPath):
    if radio != prevRadio:
         return '/{}'.format(radio)
    elif path != prevPath:
         return path

@app.callback(Output('radio', 'value'), [Input('store', 'children')])
def update_radio(path):
    return path

@app.callback(Output('location', 'pathname'), [Input('store', 'children')])
def update_path(path):
    return path

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.

4reactions
chriddypcommented, Nov 6, 2017

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/):

Suppose that an extra $17 was charged to 85% of vehicle registrations. Park admission would be free for those who paid the charge. This would collect an extra $338 million for a total state park budget of $738 million.

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.

Read more comments on GitHub >

github_iconTop Results From Across the Web

dcc.Location - Dash for Python Documentation - Dash Plotly
Location. The dcc.Location component represents the location or address bar in your web browser. Through its href , pathname , search and hash...
Read more >
Plotly Dash URL pathname callback not firing when loading ...
You need to add a dcc.Location object to your layout, and its id should match the one you are using on the callback...
Read more >
Python Examples of dash_core_components.Location
Link component updates the `Location` pathname # without refreshing the page dcc.Link(html.A('Go to page 2 without refreshing!'), href="/page-2" ...
Read more >
多页面应用程序和URL 支持— Dash 手册 - GitHub Pages
Location(id='url', refresh=False), dcc. ... dcc.Location 组件表示web 浏览器中的位置或地址栏。通过它的 href , pathname , search 和 hash 属性,你可以访问应用 ...
Read more >
Advancing to Professional Dashboard with Python, using Dash
Location to get the current web application URL. app.layout = html.Div( [ dcc.Location(id="url", refresh=False), html.Div(id="page-content"), ]
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found