Bring Drag & Drop to Dash with Dashboard Engine. 💫 Learn how at our next webinar!

Tooltip problem with callback plot - example code included

I am having an interesting time using Dash for plotting. I was able to get everything working with a regular px.line to show appropriate annotations on hover tooltip; but when I tried to copy an example to add callbacks to allow choosing data, the tooltip changes and only shows the actual point data, none of the other data applicable to that “row” of the dataframe.

I have tried a lot of things to manipulate it, but can’t figure it out. Full working example below.

The tooltip I want is – https://i.imgur.com/3VOcHHE.png - and you can see it when hovering on the lower graph points

What I get when generated by the callback is – https://i.imgur.com/izhpu6J.png

What I would also like to do… is for any points where an Annotation exists, change the dot marker to something so it’s more obvious.

# -*- coding: utf-8 -*-

# Run this app with `python app.py` and
# visit http://127.0.0.1:8050/ in your web browser.

import dash
import dash_core_components as dcc
import dash_html_components as html
import plotly.express as px
import pandas as pd
from dash.dependencies import ClientsideFunction, Input, Output
import types


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

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

# assume you have a "long-form" data frame
# see https://plotly.com/python/px-arguments/ for more options

jsonData ={"NAME":{"0":"HL","1":"HL","2":"HL","3":"HL","4":"HL","5":"HL","6":"HL","7":"HL","8":"HL","9":"HL",},"month":{"0":1,"1":2,"2":3,"3":4,"4":5,"5":6,"6":7,"7":8,"8":11,"9":12},"sales":{"0":987.0,"1":3983.0,"2":359.0,"3":2724.0,"4":4317.0,"5":2860.99,"6":5744.0,"7":2441.0,"8":1317.0,"9":878.0,},"Annotation":{"0":"","1":"","2":"","3":"","4":"","5":"","6":"","7":"Partial Brand!","8":"","9":""}}


import json

df = pd.DataFrame(jsonData)
print(df)
available_brands = df['NAME'].unique()
fig = px.line(df, x="month", y="sales", color="NAME" , hover_data=['Annotation'])
fig2 = px.line(df, x="month", y="sales", color="NAME" , hover_data=['Annotation'])


app.layout = html.Div(children=[
    html.H1(children='DashApp'),

    html.Div(children='''
        Vendor Charts: Review of sales against events.
    '''),

    dcc.Graph(
        id='clientside-graph',
        figure=fig
    ),
    dcc.Graph(
        id='test',
        figure=fig2
    ),
    dcc.Store(
        id='clientside-figure-store',
        data=[{
            'x': df[df['NAME'] == 'HL']['month'],
            'y': df[df['NAME'] == 'HL']['sales'],
            'Annotation' : df[df['NAME'] == 'HL']['Annotation']
        }]
    ),
    dcc.Dropdown(
        id='clientside-graph-indicator',
        options=[
            {'label': brand, 'value': brand}
            for brand in available_brands
        ],
        value='',
        multi=True
    ),
    html.Hr(),
        html.Details([
            html.Summary('Contents of figure storage'),
            dcc.Markdown(
                id='clientside-figure-json'
            )
        ])
    ])
@app.callback(
    Output('clientside-figure-store', 'data'),
    Input('clientside-graph-indicator', 'value'),
)
def update_store_data( brand):
    #dff = df[df['NAME'] == brand]
    
    if type(brand) is list:
        pass
    else:
        brand = [brand]

    print(type(brand))
    print(brand)
    dff = df[df['NAME'].isin(brand)]
    return [{
        'x': dff['month'],
        'y': dff['sales'],
        'color': dff['NAME'],
        'hover_data': [dff['Annotation']],
    }]

app.clientside_callback(
    """
    function(data, scale) {
        return {
            'data': data,
            'layout': {
                 'yaxis': {'type': scale},
                 'title':'test'
                
             }
        }
    }
    """,
    Output('clientside-graph', 'figure'),
    Input('clientside-figure-store', 'data'),
)


@app.callback(
    Output('clientside-figure-json', 'children'),
    Input('clientside-figure-store', 'data')
)
def generated_figure_json(data):
    return '```\n'+json.dumps(data, indent=2)+'\n```'

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