Dash Reset Axes range not updating if ranges specified in Layout

If the figure in a Dash Graph is updated via callback and the new figure has ranges specified for the x and y axes the Reset Axes tool will reset the axes to those from the original figure. If no ranges are specified in the new figure Layout, Reset Axes will reset the axes to values appropriate for the new figure.

See Dash Reset Axes Range - Pastebin.com for my contrived example. If you select Log Plot from the dropdown menu then click the Reset Axes button the y axis range is set to 10 to 10^500. If you remove the range=yrange from the yaxis definition in the layout, Reset Axes behaves as expected in the Log Plot.

Is there some way to have Reset Axes use the ranges specified in the Layout when updating a figure? Setting uirevision to a changing value in the layout did not work.

Thanks

1 Like

Hi,

I am having the same problem and I was able to figure out a hacky workaround. Have you (or anyone else) found a proper solution for this problem?

My solution consists of having the callback update both the figure (from a dcc.Graph component) as well as the children of a html.Div to [dcc.Store(id=“store”, data=figure)] and then taking the store as another input for the callback updating the figure. If the trigger for the callback was this store, simply return its data as the figure and [dcc.Store(id=“store”, data=None)] as the children of the html.Div. If the data of the store was None, raise PreventUpdate.
This is definitely very hacky however…

I know this is an old problem, but it just bit me and i couldnt find a proper solution.
Anyways after trying some stuff i found a decent solution myself:

Instead of updating the figure, or dcc.Graph i now update the entire html.div.

I have taken your example and fixed it to show it, see below.

I have also done some testing:
When i add a random number to the id it works aswell. So i am guessing the callback somehow remembers the graph id, so when you press reset axes it looks back to the first time it generated that graph instead of the last time it was updated via a callback. When you update the div that contains the graph this somehow breaks.


import dash
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import Input, Output
import plotly.graph_objs as go
import math

app = dash.Dash(name)
server = app.server
app.title = ‘resetScale2d Test’

_config = {‘modeBarButtons’: [[‘resetScale2d’]]}

def make_fig(plot_type=‘linear’, x=range(21), y=range(1, 211, 10)):
xvals = list(x)
yvals = list(y)
xrange = [0, 50]
yrange = [1, 500]
if plot_type == ‘log’:
yrange = [math.log10(yr) for yr in yrange]
print(plot_type, xrange, yrange)
traces = [go.Scatter(x=xvals, y=yvals, marker={‘size’: 8}, name=‘Tens’)]

layout = go.Layout(
    xaxis=dict(range=xrange),
    yaxis=dict(type=plot_type,
               range=yrange),
    # uirevision=plot_type
)
fig = go.Figure(data=traces, layout=layout)


fig_div = html.Div(
        [dcc.Graph(id='linlogplot', figure=fig, config=_config)],
        id='fig_div',
    )

return fig_div

app.layout = html.Div(
[
dcc.Dropdown(
id=‘linlog’,
options=[
{‘label’: ‘Linear Plot’, ‘value’: ‘linear’},
{‘label’: ‘Log Plot’, ‘value’: ‘log’},
],
value=‘linear’,
),
make_fig(),
]
)

@app.callback(Output(‘fig_div’, ‘children’), [Input(‘linlog’, ‘value’)])
def change_type(plot_type):
return make_fig(plot_type=plot_type)

if name == ‘main’:
app.run_server()

2 Likes

I’m not sure why this works, but it does.
I figured that nesting a new div in another div should also work (following this logic), but it doesn’t.
This issue has been around for a while…it would be nice if it was properly fixed…