Black Lives Matter. Please consider donating to Black Girls Code today.
Dash HoloViews is now available! Check out the docs.

How to output results in dash bootstrap Toast component?

I did but it is not returning in the webapp but it is printing in console.

Well, you need to review the boostrap Toast first.

See that in the example uses Output(“auto-toast”, “is_open”) to change from False to True to show the component.

First try just to do the Toast work alone (out of your program) and then add to it.

Hope it helps.

Hey @matsujju

There’s some bits missing from your code so I couldn’t run it exactly, but I made a minimal working example of toasts displaying results to the user.

import json
from random import randint
from uuid import uuid4

import dash
import dash_bootstrap_components as dbc
import dash_core_components as dcc
import dash_html_components as html
from dash.dependencies import ALL, Input, Output, State

app = dash.Dash(external_stylesheets=[dbc.themes.BOOTSTRAP])

app.layout = dbc.Container(
    [
        # store will save all messages to display to the user
        # this is client-side so user specific
        dcc.Store(id="message-store"),
        html.H1("Toast demo"),
        html.P(
            "Click on generate, you'll get a random number pop up in a toast"
        ),
        dbc.Button("Generate number", id="button"),
        # create a container for the toasts and position to the top right
        html.Div(
            id="toast-container",
            style={"position": "fixed", "top": 10, "right": 10, "width": 350},
        ),
    ],
    className="p-5",
)


@app.callback(
    Output("message-store", "data"),
    [
        Input("button", "n_clicks"),
        Input({"type": "toast", "id": ALL}, "n_dismiss"),
    ],
    [State("message-store", "data")],
)
def manage_store(n, dismissed_toast, store):
    """
    This callback manages the message store.
    If the "generate" button is clicked we add an item to the store
    If one of the toasts is dismissed we remove the corresponding item from the
    store.
    To figure out which of these happened, we use callback context.
    """
    ctx = dash.callback_context
    triggered = ctx.triggered[0]["prop_id"]
    if n and triggered == "button.n_clicks":
        # button has been clicked, return a new list of messages
        # generate a random id using uuid.uuid4
        return [*store, {"number": randint(0, 100), "id": str(uuid4())}]
    elif triggered.endswith(".n_dismiss"):
        id_, _ = triggered.split(".")
        # recover id of dismissed toast
        id_ = json.loads(id_)["id"]
        # filter it from the store
        return [item for item in store if item["id"] != id_]
    return []


def make_toast(message, id_):
    """
    Helper function for making a toast. dict id for use in pattern matching
    callbacks.
    """
    return dbc.Toast(
        message,
        id={"type": "toast", "id": id_},
        key=id_,
        header="Positioned toast",
        is_open=True,
        dismissable=True,
        icon="danger",
    )


@app.callback(
    Output("toast-container", "children"), Input("message-store", "data")
)
def display_toasts(store):
    """
    When the store updates, update the displayed toasts.
    """
    return [
        make_toast(f"A random number: {item['number']}", item["id"])
        for item in store
    ]


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

Here’s how it works:

  • Messages that should be shown to the user are saved in a dcc.Store alongside an id so you can keep track of which message is which.
  • Anytime the store is updated, a callback keeps the toasts up to date.
  • A second pattern-matching callback keeps the store up to date, watching for new messages being created, and also watching for any of the toasts to be dismissed. If any of them are dismissed it will remove them from the store.

Hope you will be able to apply similar logic to your app!

Thanks for your example but can you tell me what is the issue in my code and why I am not able to output the result in frontend side (webapp though the results are printing in console on printing).
Moreover, I haven’t used dash.callback_context earlier and count be beginner in Dash, so I want to keep things simple that’s why I used my Toast inside layout and is it necessary to use Store with Toast component?
I don’t mind using another component for output if Toast is not working out. I just to show the results to user in clear, elegant way.

I tried your way though Toast is now showing in dashboard but not the result not even empty list.
I am attaching the screenshot.

Are you passing [] as the children of the toast? When you pass children to a Dash component, if it finds a list it assumes it’s a list of children to display. An empty list of children is the same as no children, i.e. no content and hence an empty toast. What happens if you return something like str(results) from the callback? In that case you might see a [] displayed.

what is the issue in my code and why I am not able to output the result in frontend side

I wasn’t able to easily figure that out because as mentioned I couldn’t run your code, but I think it’s probably a combination of:

  • Not setting is_open=True on the Toasts, which means they are hidden
  • Setting the children of the toast to equal [] which is equivalent to having no content.

I have done both but still results are not shown in webapp but Toast component is now showing.

Yes it is printing empty list in console.

It will be possible that you was not able to reproduce it as I just gave layout and callbacks but I have many custom functions for preprocessing of data and some pickle files loading which I might not able to provide.

But are you actually returning anything? Printing will only display stuff in the console, you need to return something from the callback. If there is no explicit return statement then the callback will return None and the toast will be empty.

As far as I can tell in this example you aren’t returning anything in the callback, you’re just printing:

@app.callback(
    Output("output-state", "children"),
    [Input("submit-button", "n_clicks")],
    [
        State("input_text", "value"),
        State("slider", "value"),
        State("drop-down", "value"),
        State("slider-2", "value"),
    ],
    # prevent_initial_call=True,
)
def label_prediction(num_clicks, text, threshold_value, preprocess_func, label_value):
    if text is None:
        raise PreventUpdate

    if num_clicks > 0:
        params = ["remove_digits", "remove_stopwords", "text_lemmatization"]
        dict_params = [param in preprocess_func for param in params]
        preprocess_text = preprocess(text, *dict_params)
        transformed_text = tfidf.fit_transform([preprocess_text])
        prediction = classifier.predict_proba(transformed_text)
        print(f"Predicted labels:{get_tags(prediction[0],threshold_value,label_value)}")

Oh no…you misunderstood it…I am returning that was just to show that I used print also inside the function along with return.

def label_prediction(num_clicks, text, threshold_value, preprocess_func, label_value):
    if text is None or num_clicks is None:
        return dash.no_update
    else:

        params = ["remove_digits", "remove_stopwords", "text_lemmatization"]
        dict_params = [param in preprocess_func for param in params]
        preprocess_text = preprocess(text, *dict_params)
        transformed_text = tfidf.fit_transform([preprocess_text])
        prediction = classifier.predict_proba(transformed_text)
        # print("This is the result to show")
        result = get_tags(prediction[0], threshold_value, label_value)
        print(str(result))
        return result