How to output a value in an html.div?

Question:

I have a function that prints a random value.
The function is ‘activated’ when the button Start is pressed.

            print("acquisition is on")
            print(random.random())

At the moment the random value is printed in the console. But I am wondering how to directly output this value in the html.Div.

Below is the full code

from dash import Dash, html, dcc, Input, Output, ctx
import dash_bootstrap_components as dbc
import time
import threading
import random


app = Dash(
    __name__,
    external_stylesheets = [dbc.themes.SPACELAB, dbc.icons.FONT_AWESOME],
    title = 'MT',
    prevent_initial_callbacks = "initial_duplicate"
)



class Nanotec(threading.Thread):

    def __init__(self, *args, **kwargs):
        # When Main is excuted, this does :
        super(Nanotec, self).__init__(*args, **kwargs)
        self.__flag = threading.Event() # The flag used to pause the thread
        self.__flag.set() # Set to True
        self.__running = threading.Event() # Used to stop the thread identification
        self.__running.set() # Set running to True
        

    def run(self):
        while self.__running.isSet():
            self.__flag.wait() # return immediately when it is True, block until the internal flag is True when it is False
            print("acquisition is on")
            print(random.random())
            time.sleep(1)


    def pause(self):
        self.__flag.clear() # Set to False to block the thread
        print("pausing")

    def resume(self):
        self.__flag.set() # Set to True, let the thread stop blocking
        print("resuming")

    def stop(self):
        self.__flag.set() # Resume the thread from the suspended state, if it is already suspended
        self.__running.clear() # Set to False


@app.callback(Output('container', 'children'),
              Input('btn_start_nanotec', 'n_clicks'),
              Input('btn_pause_nanotec', 'n_clicks'),
              Input('btn_resume_nanotec', 'n_clicks')
              )
def display(btn_start_nanotec, btn_pause_nanotec, btn_resume_nanotec):
        button_id = ctx.triggered_id if not None else 'No clicks yet'
        if button_id == "btn_start_nanotec" :
            my_thread_nanotec.start()
        elif button_id == "btn_pause_nanotec" :
            my_thread_nanotec.pause()
        elif button_id == "btn_resume_nanotec" :
            my_thread_nanotec.resume()

my_thread_nanotec = Nanotec()

app.layout = html.Div([
    html.Button('Start', id='btn_start_nanotec'),
    html.Button('Pause', id='btn_pause_nanotec'),
    html.Button('Resume', id='btn_resume_nanotec'),
    html.Div(id='container'),
    html.Br(),

])

if __name__ == "__main__":
   app.run_server(debug = True)
Asked By: 2WFR

||

Answers:

I am not quite sure what are you trying to do here regarding that multithreading class. Is it supposed to update html.Div one time per second? Is text supposed to be updated on button click?

But since the question is "How to put a value…", here’s a quick explanation. I replaced multithreading class with a simple generator to make things clearer.
Your callback is supposed to return the value to put into html.Div. So here the value is fetched from the generator (when the button is clicked) and returned:

import random
from dash import Dash, html, dcc, Input, Output, ctx


app = Dash(__name__, title="MT", prevent_initial_callbacks="initial_duplicate")

def randoms():
    while True:
        yield random.random()


random_iter = randoms()


@app.callback(
    Output(component_id="container", component_property="children"),
    Input("btn_start_nanotec", "n_clicks"),
    Input("btn_pause_nanotec", "n_clicks"),
    Input("btn_resume_nanotec", "n_clicks"),
)
def display(*_):
    button_id = ctx.triggered_id
    if button_id == "btn_start_nanotec":
        result = next(random_iter)
    elif button_id == "btn_pause_nanotec":
        result = 'Pause?..'
    elif button_id == "btn_resume_nanotec":
        result = next(random_iter)
    return result


app.layout = html.Div(
    [
        html.Button("Start", id="btn_start_nanotec"),
        html.Button("Pause", id="btn_pause_nanotec"),
        html.Button("Resume", id="btn_resume_nanotec"),
        html.Div(id="container"),
        html.Br(),
    ]
)

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

You can replace my super-simple iterator with anything else (threading.Thread, multiprocessing.Pool, whatever), but the callback still has to get the value from the source and return it.

Intervals

If you need to update the output periodically (once per second), take a look into Intervals. The same basic principle works just the same (callback returns value), but it would handle periodical updates for you.

Updating Input with Websocket messages

Websocket component seems to fit the bill quite nicely: data sent by another process/thread and updated in (sort of) real time, even bidirectional communication (pause/resume) is supported.

Answered By: Nikolaj Š.
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.