plotly / plotly.js

Open-source JavaScript charting library behind Plotly and Dash
https://plotly.com/javascript/
MIT License
17.14k stars 1.87k forks source link

rangeslider template bug (non-attribute inserted into layout instead of fullLayout) #6310

Open alexcjohnson opened 2 years ago

alexcjohnson commented 2 years ago

When you add a rangeslider, its yaxis container gets _template: null inserted into the input (layout) object. This isn't an attribute, so it should only be inserted in the fullLayout object, not the layout object.

https://codepen.io/alexcjohnson/pen/vYjOvgJ

This doesn't cause problems directly in plotly.js, but it should be fixed here because it can cause problems in Dash if you reload a figure into Python after displaying it on the page, for example:

from dash import Dash, dcc, html, callback, Input, Output, State
import random
import datetime
import plotly.graph_objects as go

app = Dash(__name__)

app.layout = html.Div([
    html.Div(style={'display': 'flex'}, children=[
        dcc.Graph(
            id='graph-ph',
             figure={
                 'data': [
                     {'x':  [],
                      'y': [0, random.random()],
                      'mode':'lines+markers',
                      }],
                 'layout': {
                     'title': 'pH (pH)'
                 }},
             ),
]),
    dcc.Interval(
        id='interval-graph-update',
        interval=3000,
        max_intervals=3),
])

@callback(
    Output('graph-ph', 'figure'),
    Input('interval-graph-update', 'n_intervals'),
    State('graph-ph', 'figure')
    )
def update_extend_traces_traceselect(n_intervals, fig_raw):
    x_new = datetime.datetime.now()
    y_new = random.random()

    fig_raw['data'][0]['x'] = fig_raw['data'][0]['x'] + [x_new]
    fig_raw['data'][0]['y'] = fig_raw['data'][0]['y'] + [y_new]

    fig = go.Figure(fig_raw)
    fig.update_xaxes(rangeslider={'visible': True})

    return fig

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

Which gives the error (from the line fig = go.Figure(fig_raw) on the second callback call):

ValueError: Invalid property specified for object of type
plotly.graph_objs.layout.xaxis.rangeslider.YAxis: '_template'

Until this is fixed, removing the problematic container (you could even remove just _template) can avoid the error:

    # add these lines before fig = go.Figure(fig_raw)
    if 'rangeslider' in fig_raw['layout']['xaxis']:
        del fig_raw['layout']['xaxis']['rangeslider']['yaxis']
ssg-data commented 11 months ago

very helpful tip above about deleting the problematic piece before go.Figure(fig_raw).