Simple dash app. Yaxis autoscale on xaxis zoom in stock market plot

So I did manage to get the desired behavior by using the State dependency. Performance does take a big hit due to the fact that the graph have to be re-imported every time the ‘relayoutData’ is being called. I haven’t found any better implementation so far. I wish there was a way of only updating the graph layout, or better yet the ‘yaxis’ part of the layout through the callback. That way dash would only refresh the required element and performance would be great.

I suggest adding a tree structure to the property tags. For instance in this example the Output element should be like this: Output(‘RandGraph’,‘figure.layout.yaxis’). The pandas method I implemented to find the min and max of y, based on active xaxis range works good enough, but would be great if there was a native ymin, ymax function based on active datafilters.

Here is the code for anyone interested:

import dash
from dash.dependencies import Output, Input, State
import dash_core_components as dcc
import dash_html_components as html
import plotly.graph_objs as go
import numpy as np
import pandas as pd
import datetime

#some random values
a = datetime.datetime.today()
numdays = 100
dateList = []
for x in range (0, numdays):
    dateList.append(a - datetime.timedelta(days = x))
xy = [dateList,np.random.rand(100)]

df = pd.DataFrame(data=xy[1],columns=["y"],index=xy[0])

app = dash.Dash()

app.title = 'Random'

dataS = [dict(
    x = df.index,
    y = df['y'],
    name = 'OL meter',
    mode = 'lines'
)]

def uptLayout(yaxRang):
    return 


layoutS = go.Layout(
    title="OL Meter",
    xaxis=dict(
        rangeslider_visible=True,
        rangeselector=dict(
            buttons=list([
                dict(count=0, label="1m", step="month", stepmode="backward"),
                dict(count=6, label="6m", step="month", stepmode="backward"),
                dict(count=1, label="YTD", step="year", stepmode="todate"),
                dict(count=1, label="1y", step="year", stepmode="backward"),
                dict(count=5, label="5y", step="year", stepmode="backward"),
                dict(step="all")
            ])
        )
    ),
    yaxis=dict(range=[0,2])
)


app.layout = html.Div(
    html.Div([
        html.H1(children='Random nums'),
        html.Div(children='''
            Rand rand rand.
        '''),
        
        dcc.Input(
            id='input-y',
            placeholder='Insert y value',
            type='number',
            value='',
        ),
        html.Div(id='result'),
        
        dcc.Graph(id='RandGraph',figure=dict(data=dataS,layout=layoutS))
    ])
)

@app.callback(
    Output('RandGraph','figure'),
    [Input('RandGraph','relayoutData')],[State('RandGraph', 'figure')]
)
def update_result(relOut,Fig):
    ymin = df.loc[relOut['xaxis.range'][1]:relOut['xaxis.range'][0],'y'].min()
    ymax = df.loc[relOut['xaxis.range'][1]:relOut['xaxis.range'][0],'y'].max()
    newLayout = go.Layout(
        title="OL Meter",
        xaxis=dict(
            rangeslider_visible=True,
            rangeselector=dict(
                buttons=list([
                    dict(count=0, label="1m", step="month", stepmode="backward"),
                    dict(count=6, label="6m", step="month", stepmode="backward"),
                    dict(count=1, label="YTD", step="year", stepmode="todate"),
                    dict(count=1, label="1y", step="year", stepmode="backward"),
                    dict(count=5, label="5y", step="year", stepmode="backward"),
                    dict(step="all")
                ])
            ),
            range=relOut['xaxis.range']
        ),
        yaxis=dict(range=[ymin,ymax])
    )
    
    
    Fig['layout']=newLayout
    return Fig



if __name__ == '__main__':
    app.run_server(debug=False)