Client reactivity
When aclient statechanges, the browser updates the display itself — with no request. One wires that by passing a binding to a reactive prop.
Reading a client state = a binding
Reading a ClientState field inside a render does not return the raw value but a `ClientBinding` — an object the component knows how to wire.| Passed to… | Cable |
|---|---|
| ui.text(binding) | bz-text — the text follows the value |
| visible=binding | bz-show — shown/hidden according to the value |
| value=binding (input) | bz-model — two-way read/write |
Displaying a value
A server value read inside a render is an ordinary Python value: one displays it directly (str, f-string). A ClientBinding is passed as is to `ui.text()` to stay reactive; interpolating it into a `str()` or an f-string raises an error.Demo — a binding drives a bz-show
Demo — a ClientExpression drives visible=
The operators on a binding (`num.n > 3`) compose a `ClientExpression`, baked into a client-side `bz-show`. Zero round trips.n > 3
The whole binding → JS algebra
Every `ClientBinding` operator and method, read live from the class, with the JS it really emits (captured by running a probe). Adding an operator to the algebra adds it here — with no editing. Traps: `&`/`|`/`~` (not `and`/`or`/`not`), and parenthesise compound comparisons `(x > 0) & (y < 10)`.comparison13
| In Python | Emitted JS (live) | → |
|---|---|---|
| x == y | ($bz.state.State.default.x === 3) | ClientExpression |
| x >= y | ($bz.state.State.default.x >= 3) | ClientExpression |
| x > y | ($bz.state.State.default.x > 3) | ClientExpression |
| x <= y | ($bz.state.State.default.x <= 3) | ClientExpression |
| x < y | ($bz.state.State.default.x < 3) | ClientExpression |
| x != y | ($bz.state.State.default.x !== 3) | ClientExpression |
| x.between(lo, hi) | ($bz.state.State.default.x >= 1 && $bz.state.State.default.x <= 10) | ClientExpression |
| x.eq(y) | ($bz.state.State.default.x === 3) | ClientExpression |
| x.ge(y) | ($bz.state.State.default.x >= 3) | ClientExpression |
| x.gt(y) | ($bz.state.State.default.x > 3) | ClientExpression |
| x.le(y) | ($bz.state.State.default.x <= 3) | ClientExpression |
| x.lt(y) | ($bz.state.State.default.x < 3) | ClientExpression |
| x.ne(y) | ($bz.state.State.default.x !== 3) | ClientExpression |
arithmetic13
| In Python | Emitted JS (live) | → |
|---|---|---|
| abs(x) | Math.abs($bz.state.State.default.x) | ClientExpression |
| x + y | ($bz.state.State.default.x + 3) | ClientExpression |
| x // y | Math.floor($bz.state.State.default.x / 3) | ClientExpression |
| x % y | ($bz.state.State.default.x % 3) | ClientExpression |
| x * y | ($bz.state.State.default.x * 3) | ClientExpression |
| -x | (-$bz.state.State.default.x) | ClientExpression |
| y + x | (3 + $bz.state.State.default.x) | ClientExpression |
| y * x | (3 * $bz.state.State.default.x) | ClientExpression |
| round(x, n) | Math.round($bz.state.State.default.x) | ClientExpression |
| y - x | (3 - $bz.state.State.default.x) | ClientExpression |
| x - y | ($bz.state.State.default.x - 3) | ClientExpression |
| x / y | ($bz.state.State.default.x / 3) | ClientExpression |
| x.to_fixed(n) | Number($bz.state.State.default.x).toFixed(2) | ClientExpression |
logic5
| In Python | Emitted JS (live) | → |
|---|---|---|
| x & y | ($bz.state.State.default.x && $bz.state.State.default.y) | ClientExpression |
| ~x | (!$bz.state.State.default.x) | ClientExpression |
| x | y | ($bz.state.State.default.x || $bz.state.State.default.y) | ClientExpression |
| x.not_() | (!$bz.state.State.default.x) | ClientExpression |
| cond.then_else(a, b) | ($bz.state.State.default.x ? 1 : 10) | ClientExpression |
list3
| In Python | Emitted JS (live) | → |
|---|---|---|
| x.contains(v) | $bz.state.State.default.x.includes(3) | ClientExpression |
| x.join(sep) | ((($bz.state.State.default.x || []).join(", ")) || "") | ClientExpression |
| x.length() | $bz.state.State.default.x.length | ClientExpression |
mutation6
| In Python | Emitted JS (live) | → |
|---|---|---|
| x.clear() | $bz.state.State.default.x = [] | str |
| x.decrement(n) | $bz.state.State.default.x -= 1 | str |
| x.increment(n) | $bz.state.State.default.x += 1 | str |
| x.push(v) | $bz.state.State.default.x = [...($bz.state.State.default.x || []), 3] | str |
| x.set(v) | $bz.state.State.default.x = 3 | str |
| x.toggle() | $bz.state.State.default.x = !$bz.state.State.default.x | str |