Documentation Index
Fetch the complete documentation index at: https://prefab.prefect.io/docs/llms.txt
Use this file to discover all available pages before exploring further.
The Reactivity page introduced {{ count + 1 }} as a way to compute new values from state. Expressions support a full set of operators — arithmetic, comparisons, boolean logic, and conditionals — that let you build complex display logic without leaving the browser.
Here’s a component that uses several of them together: arithmetic to increment and decrement a quantity, multiplication to compute a total, and a formatting pipe to display it as currency.
The rest of this page walks through each operator type. Every example shows the Python Rx syntax and the {{ }} protocol expression it compiles to.
Arithmetic
Rx objects overload Python’s arithmetic operators, so price * quantity in your Python code compiles to {{ price * quantity }} in the protocol. The quantity selector above uses addition, subtraction, and multiplication — here’s the full set:
| Python | Protocol | Description |
|---|
count + 1 | {{ count + 1 }} | Addition |
total - discount | {{ total - discount }} | Subtraction |
price * quantity | {{ price * quantity }} | Multiplication |
amount / 2 | {{ amount / 2 }} | Division |
-score | {{ -score }} | Negation |
Arithmetic expressions can appear anywhere a value is expected — in a Text component, in a SetState action, or in a prop like Progress(value=...). The renderer evaluates them against current state each time a referenced key changes.
String Concatenation
The + operator does double duty: if either operand is a string, it concatenates instead of adding. But in Python, f-strings are almost always the better choice for mixing reactive values with literal text. Each Rx reference inside an f-string becomes a separate {{ }} interpolation in the output:
In the protocol, you can also concatenate with + inside a single expression: {{ 'Hello, ' + first + ' ' + last + '!' }}. F-strings are almost always cleaner.
Comparison
Six comparison operators return boolean values. On their own, a boolean isn’t very useful in a Text component — but comparisons are the foundation for two things you’ll use constantly: conditional rendering with If/Elif/Else, and conditional values with the ternary operator (covered below).
| Python | Protocol | Meaning |
|---|
count > 0 | {{ count > 0 }} | Greater than |
count >= 10 | {{ count >= 10 }} | Greater than or equal |
count < 100 | {{ count < 100 }} | Less than |
count <= 50 | {{ count <= 50 }} | Less than or equal |
status == 'active' | {{ status == 'active' }} | Equal (loose) |
status != 'done' | {{ status != 'done' }} | Not equal |
Here’s the most common pattern — showing different content based on a state value:
from prefab_ui.rx import Rx
from prefab_ui.components import Alert
from prefab_ui.components.control_flow import If, Elif
inventory = Rx("inventory")
with If(inventory == 0):
Alert("Out of stock", variant="destructive")
with Elif((inventory > 0) & (inventory < 10)):
Alert("Low stock")
The If component receives a boolean expression and only renders its children when the expression is true. When inventory changes, the conditions re-evaluate and the UI updates to show the right alert.
Logical
Boolean operators combine multiple conditions. Python doesn’t allow overloading and, or, and not, so Rx uses the bitwise operators &, |, and ~ instead. They compile to &&, ||, and ! in the protocol:
| Python | Protocol | Meaning |
|---|
a & b | {{ a && b }} | Logical AND |
a | b | {{ a || b }} | Logical OR |
~a | {{ !a }} | Logical NOT |
The protocol also accepts keyword forms and, or, and not — use whichever reads better in context.
Both && and || short-circuit, which makes || useful as a default-value mechanism: {{ name || 'Anonymous' }} returns 'Anonymous' when name is falsy (undefined, empty string, false, or 0).
Python precedence gotcha. Bitwise & and | bind tighter than >, <, ==, etc. in Python. Without parentheses, score > 0 & score < 100 parses as score > (0 & score) < 100, which is not what you want. Always wrap each comparison in parentheses when combining with & or |:# Correct
(score > 0) & (score < 100)
# Wrong — parsed as score > (0 & score) < 100
score > 0 & score < 100
This is a Python quirk, not a Prefab one. The protocol’s {{ }} expressions don’t have this issue — && and || have lower precedence than comparisons there.
Ternary
Sometimes you need to choose between two values based on a condition — “Online” or “Offline”, “Pass” or “Fail”, one color or another. The .then(if_true, if_false) method on Rx handles this, compiling to the protocol’s condition ? ifTrue : ifFalse syntax:
Toggle the switch — the text updates instantly between “Online” and “Offline”.
| Python | Protocol |
|---|
active.then("On", "Off") | {{ active ? 'On' : 'Off' }} |
(score > 90).then("Pass", "Fail") | {{ score > 90 ? 'Pass' : 'Fail' }} |
Ternaries can technically be nested — (score > 90).then("A", (score > 80).then("B", "C")) — but readability suffers quickly. For anything beyond a simple two-way choice, If/Elif/Else is almost always cleaner.
When in doubt about any expression, add parentheses. The Rx DSL handles parenthesization automatically in the compiled output, so explicit parens in Python never hurt.