Reading & Updating Datastar Signals + Patching Elements ¶
Read Signal Values ¶
from stario.datastar import Signal
@app.query("/page")
async def page(counter: Signal[int] = 0):
# Read a signal value via dependency
return div(f"Counter: {counter}")
Multiple Signals ¶
from stario.datastar import Signal
@app.query("/greet")
async def greet(name: Signal[str], age: Signal[int]):
return div(f"Hello {name}, you are {age} years old")
Initialize & Update Signals ¶
from stario.datastar import Attributes
from stario.html import div, button, span
@app.query("/counter")
async def counter_page(attr: Attributes):
return div(
attr.signals({"count": 0}), # Initialize signal with value
span(attr.text("$count")), # Display signal value as text
button(attr.on("click", "$count++"), "Increment"), # Increment signal value on click
)
Update Signals via Yield ¶
from stario.datastar import Signal
from stario.html import div
async def increment(counter: Signal[int] = 0):
new_count = counter + 1 # Local change
# Yield updated signal value as dictionary
yield {"counter": new_count} # Send updated signal value to frontend
Patch HTML Elements ¶
Patch modes determine how elements are updated:
Outer (morphs existing element): This should be what you need most of the time: it will take new element and morph the existing element with it.
# Will morph the existing element with id "message" with new element (default mode)
yield div({"id": "message"}, "Hello World!")
Replace (default - morphs existing element):
from stario.html import div
@app.command("/update-text")
async def update_text():
# Will replace element with id "message" with new element
yield "replace", "#message", div({"id": "message"}, "Hello World!")
Append (add to end of container):
# Will add new element to the end of the element with id "list"
yield "append", "#list", div({"class": "item"}, "New item")
Prepend (add to start of container):
# Will add new element to the start of the element with id "list"
yield "prepend", "#list", div({"class": "item"}, "First item")
Remove (delete element):
# Will remove element with id "message"
yield "remove", "#message"
See Datastar Reference for complete patching documentation, including outer, inner, and advanced options.
Streaming Updates ¶
When handler is a generator (uses yield), Stario will convert it to a streaming response compatible with Datastar SSE events.
You can use it to stream just one update, or many updates over time, or just have a long lived stream that awaits on the queue for new updates and sends them to the client.
There's no limit to the duration of the stream, and you can send any number of updates to the client.
from stario.html import div
import asyncio
@app.query("/stream-updates")
async def stream_updates():
for i in range(5):
yield {"progress": i * 20}
await asyncio.sleep(1)
Key Concepts ¶
Signal[type]- Dependency to read signal values from requestsAttributes- Generatedata-*attributes for reactive bindingActions- Generate Datastar HTTP actions- Yield dictionaries - Update signals:
yield {"key": value} - Yield tuples - Patch elements:
yield "mode", "selector", element
