07: Signal input
A button click that emits a signal with a payload (
{n_clicks, random_number}); a separate callback receives the payload and updates a label. The canonical producer/consumer signal pattern.
The script
import random
from dash import html
from dash_extensions.enrich import Output, Input
from weaverlet.base import SignalOutput, SignalInput, WeaverletComponent, WeaverletApp, Identifier
from weaverlet.components import SignalComponent
class SignalInputComponent(WeaverletComponent):
trigger_button_id = Identifier()
label_p_id = Identifier()
def __init__(self, **kwargs):
super().__init__(**kwargs)
self.signal_component = SignalComponent()
def get_layout(self):
return html.Div(
[
self.signal_component(), # child component
html.Button('Click to trigger signal with input',
id=self.trigger_button_id),
html.P(id=self.label_p_id)
]
)
def register_callbacks(self, app):
@app.callback(
SignalOutput(self.signal_component),
Input(self.trigger_button_id, 'n_clicks')
)
def button_click(n_clicks):
return {'n_clicks': n_clicks, 'random_number': random.random()}
@app.callback(
Output(self.label_p_id, 'children'),
SignalInput(self.signal_component)
)
def label_update(signal_input):
return f'Signal triggered! Signal input: {signal_input}'
signal_trigger_component = SignalInputComponent()
wapp = WeaverletApp(root_component=signal_trigger_component)
wapp.app.run(port=8089)
Expected output
- The page shows a button and an empty paragraph.
- Each click updates the paragraph with the current
n_clicksand a new random number.
Notes
SignalComponentis adcc.Storeunderneath, exposed as a class-level Weaverlet object so producers and consumers reference it viaself.<signal>instead of a string ID.SignalOutput(self.signal_component)is the emit-side adapter; the producer callback must return a dict.SignalInput(self.signal_component)is the receive-side adapter; the consumer callback receives the dict as its argument.- The signal must be rendered in the layout via
self.signal_component(): otherwise the underlyingdcc.Storedoesn't exist in the DOM and the callbacks never fire. - Multiple consumers can listen to the same signal. Each consumer fires on every emission.
Try it locally
pip install weaverlet
python signal_input_app.py