Store output not being passed

Hi, I am new to Dash recently so please let me know if I should be looking elsewhere although I cannot see the solution from what I searched. The following code is 0) setting up the dcc.Store on my app page, 1a) a snip from a callbacks.py to save data when it changes in a DataTable (looks successful from the print outs in the terminal) and 1b) for a graph/figure on a separate page to the inputs from a DataTable.

However, the print output of the ‘data’ from 1a and 1b do not match. An help to get this working would be so very much appreciated.
1b just shows:
Starting graph…
data: {}
timestampe: None
data datatype: <class ‘dict’>
data timestamp: <class ‘NoneType’>

And when the DataTable gets populated (which is not what the DataTable shows)
data: (an empty list)
timestamp: 16941335413061
data datatype: <class ‘list’>
data timestamp: <class ‘int’>

# 0)
app.py:
app.layout = html.Div([dcc.Store(id="positions_store", storage_type='session',data={}),dash.page_container])


# 1a)Save DataTable data
@callback(Output('positions_store', 'data'),
    [Input('editing-rows-button', 'n_clicks'), Input('adding-rows-table', 'data')])
def save_test_data(n, data):
    print('Saving data...')
    print(data)
    print(type(data))
    print(json.dumps(data))
    print(type(json.dumps(data)))
    return json.dumps(data) if n else [{}]


# 1b) Exposure Graph:
@callback(
    Output("adding-rows-graph", "figure"),
    Input("positions_store", "modified_timestamp"),
    State("positions_store", "data")
)
def display_output(timestamp,data):
    print('Starting graph...')
    print('data: ', data)
    print('timestamp: ',timestamp)
    print('data datatype: ',type(data))
    print('data timestamp: ',type(timestamp))
    data = json.loads(data)
    print(data)
    print(data.to_dict())
    if data is None:
        raise PreventUpdate
    else:
        print('Getting to print...')
        y = pd.to_numeric([row["$ Amount"] for row in data])
        x = [row["Ticker"] for row in data]
        fig = go.Figure(go.Bar(y=y, x=x, marker_color="rgb(0, 0, 153)"))
        fig.update_layout(
            yaxis_range=[0, rf.round_sig(max(y))]
        )
        fig.layout.plot_bgcolor = "#fff"
        fig.layout.paper_bgcolor = "#fff"
    return fig

Hi @SirQuantAlot welcome to the community!

Do you need the timestamp? If not, you could try:

# 1b) Exposure Graph:
@callback(
    Output("adding-rows-graph", "figure"),
    Input("positions_store", "data")
)
def display_output(data):
    if data is None:
        raise PreventUpdate

    print('Starting graph...')
    print('data: ', data)
    print('timestamp: ',timestamp)
    print('data datatype: ',type(data))
    print('data timestamp: ',type(timestamp))
    data = json.loads(data)
    print(data)
    print(data.to_dict())

    print('Getting to print...')
    y = pd.to_numeric([row["$ Amount"] for row in data])
    x = [row["Ticker"] for row in data]
    fig = go.Figure(go.Bar(y=y, x=x, marker_color="rgb(0, 0, 153)"))
    fig.update_layout(
        yaxis_range=[0, rf.round_sig(max(y))]
    )
    fig.layout.plot_bgcolor = "#fff"
    fig.layout.paper_bgcolor = "#fff"
    return fig

Thanks for responding, but unfortunately I ran this previously and it gives an empty dictionary, with error “ValueError: max() arg is an empty sequence” with print output in the terminal:
data: {}
data datatype: <class ‘dict’>
‘Getting to print…’

# Exposure Graph:
@callback(
    Output("adding-rows-graph", "figure"),
    Input("positions_store", "data"),
)
def display_output(data):
    print('Starting graph...')
    print('data: ', data)
    #print('timestamp: ',timestamp)
    print('data datatype: ',type(data))
    #print('data timestamp: ',type(timestamp))
    # data = json.loads(data)
    # print(data)
    # print(data.to_dict())
    if data is None:
        raise PreventUpdate
    else:
        print('Getting to print...')
        y = pd.to_numeric([row["$ Amount"] for row in data])
        x = [row["Ticker"] for row in data]
        fig = go.Figure(go.Bar(y=y, x=x, marker_color="rgb(0, 0, 153)"))
        fig.update_layout(
            yaxis_range=[0, rf.round_sig(max(y))]
        )
        fig.layout.plot_bgcolor = "#fff"
        fig.layout.paper_bgcolor = "#fff"
    return fig

I was trying to follow the pattern here from the official docs on Input/State in the first example on “Store Clicks” https://dash.plotly.com/dash-core-components/store

Here is the minimal example (a run file and callbacks file along with 2 pages in an underlying pages folder: 1st page to input positions and 2nd page to graph them):
https://github.com/SirQuantAlot/TwoPageTest/tree/main

Hi @SirQuantAlot

The issue seems to be in this callback:

@callback(Output('positions_store', 'data'),
    [Input('editing-rows-button', 'n_clicks'), Input('adding-rows-table', 'data')])
def save_test_data(n, data):
    print('Saving data...')
    print(data)
    print(type(data))
    print(json.dumps(data))
    print(type(json.dumps(data)))
    return data if n else [{}]

Try changing the return to just:

return data

Thanks for your response, unfortunately I tried that but print out on terminal still shows data as an empty dictionary. Also caused an error later on “ValueError: max() arg is an empty sequence”.
Latest update in the git repo.

The issue is that in the callback to update the figure you check for:

    if data is None:
        raise PreventUpdate

But when the app starts, data is not None, it’s {}

Thanks @AnnMarieW but still getting an empty dict when I take that whole if statement out:

Terminal printed out:
data: {}

# Exposure Graph:
@callback(
    Output("adding-rows-graph", "figure"),
    Input("positions_store", "data"),
)
def display_output(data):
    print('Starting graph...')
    print('data: ', data)
    print('data datatype: ',type(data))
    print('Getting to print...')
    y = pd.to_numeric([row["$ Amount"] for row in data])
    x = [row["Ticker"] for row in data]
    fig = go.Figure(go.Bar(y=y, x=x, marker_color="rgb(0, 0, 153)"))
    fig.update_layout(
        yaxis_range=[0, max(y)]
    )
    fig.layout.plot_bgcolor = "#fff"
    fig.layout.paper_bgcolor = "#fff"
    return fig

Updated in the git: https://github.com/SirQuantAlot/TwoPageTest/tree/main

or even when i replaced

if data is None:

with

if data is {}:

Try changing it to:

   if data == {}:
        raise PreventUpdate

Thanks but unfortunately this did not work either. The print command before this shows the dict is empty.

Could you share a minimal working example or your app code?

@AnnMarieW was nice enough to confirm that the following minimal working example works on her machine:
https://github.com/SirQuantAlot/TwoPageTest/tree/main

So I think @AIMPED this must be an environment issue. I am going to create a venv and confirm the versions of modules I am using.

Many thanks to everyone for looking into this!

Just following up. After looking through libraries and updating all of them that were not latest- did not look like an environment issue. May have been some caching issues on my local because when I turned it to local from session:

dcc.Store(id="positions_store", storage_type='local',data={})

It worked i.e. store output was passing as intended!

Thanks again everyone!

2 Likes