Bug? Maintaining Interactive Graph State Across Tab Switches

I have an interactive graph in a tab. I want to be able to switch tabs, return to the tab with the graph and keep the graph’s state (like zoom, etc.). Seems like a bug that this does not happen by default. Is there anyway to force maintaining that state?

Here is a stripped down example:

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
import numpy as np


external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

fig = go.Figure()
x = [n * .1 for n in range(100)]
y = np.sin(x)
fig.add_trace(go.Scattergl(x=x, y=y, mode='lines'))

app.layout = html.Div(
    html.Div([
        html.H4('Interactive Graph in Tab Test'),
        dcc.Tabs(id="plot-tabs", value='graph',
                 children=[dcc.Tab(label='Graph', value='graph',
                                   children=[dcc.Graph(id='interactive-graph', figure=fig)]),
                           dcc.Tab(label='Other', value='other')])
    ])
)


if __name__ == '__main__':
    app.run_server(debug=True, host='0.0.0.0')

If I zoom in on the graph, click the Other tab, and then click back to the Graph tab it reverts to its original zoom.

Thanks!
Josh

I have realized that I can make this work if I use a callback and show/hide elements, but this is extra work and seems kind of hacky.

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objects as go
import numpy as np
from dash.dependencies import Input, Output


external_stylesheets = ['https://codepen.io/chriddyp/pen/bWLwgP.css']

app = dash.Dash(__name__, external_stylesheets=external_stylesheets)

fig = go.Figure()
x = [n * .1 for n in range(100)]
y = np.sin(x)
fig.add_trace(go.Scattergl(x=x, y=y, mode='lines'))

app.layout = html.Div(
    html.Div([
        html.H4('Interactive Graph in Tab Test'),
        dcc.Tabs(id="plot-tabs", value='graph',
                 children=[dcc.Tab(label='Graph', value='graph'),
                           dcc.Tab(label='Other', value='other')]),
        html.Div(id='tab-contents', children=[dcc.Graph(id='interactive-graph', figure=fig),
                                              html.Div('Other Content', id='other-content',
                                                       style={'display': 'none'})])
    ])
)


@app.callback([Output('interactive-graph', 'style'),
               Output('other-content', 'style')],
              [Input('plot-tabs', 'value')])
def tab_callback(tab_value):
    if tab_value == 'graph':
        return dict(), {'display': 'none'}
    else:
        return {'display': 'none'}, dict()


if __name__ == '__main__':
    app.run_server(debug=True, host='0.0.0.0')

Hi @jauerb thanks for the report. I’m glad you found a workaround, but this is clearly suboptimal so I opened an issue on https://github.com/plotly/dash-core-components/issues/726.