A reactive expression that captures AST for isomorphic execution.
The rx/1 macro captures an Elixir expression at compile time, storing
both the source string (for JS transpilation) and the transformed AST
(for server-side evaluation).
Usage
Use rx() to wrap expressions in calculate declarations:
calculate :tag_count, rx(length(@tags))
calculate :can_add, rx(@max == nil or length(@items) < @max)
calculate :doubled, rx(@count * 2)Supported Expressions
Expressions that can be transpiled to JavaScript:
- Arithmetic:
@count + 1,@price * @quantity - Comparisons:
@count > 0,@name == "test" - Boolean:
@enabled and @visible,not @disabled - Conditionals:
if(@count > 0, do: "yes", else: "no") - List operations:
length(@items),@items ++ ["new"] - Enum functions:
Enum.map/2,Enum.filter/2,Enum.join/2
Reusable Functions with defrx
Use defrx to define functions that can be called within rx() expressions:
defrx valid_expiry?(digits) do
String.length(digits) == 4 &&
String.to_integer(String.slice(digits, 0, 2) || "0") >= 1 &&
String.to_integer(String.slice(digits, 0, 2) || "0") <= 12
end
calculate :expiry_valid, rx(valid_expiry?(@expiry_digits))The function body is expanded inline at each call site.
Importing defrx functions from other modules
Create a module with reusable defrx functions:
defmodule MyApp.Validators do
use Lavash.Rx.Functions
defrx valid_email?(email) do
String.length(email) > 0 && String.contains?(email, "@")
end
endThen import them in your LiveView:
defmodule MyAppWeb.FormLive do
use Lavash.LiveView
import Lavash.Rx
import_rx MyApp.Validators
calculate :email_valid, rx(valid_email?(@email))
endFields
:source- The expression as a source string:ast- The transformed AST for server-side evaluation:deps- List of dependency field names (atoms)
Summary
Functions
Defines a reusable reactive function for use in rx() expressions.
Imports defrx functions from another module.
Captures a reactive expression at compile time.
Functions
Defines a reusable reactive function for use in rx() expressions.
This macro registers the function so it's available during JS generation in the ColocatedTransformer.
Examples
defrx valid_expiry?(digits) do
String.length(digits) == 4 &&
String.to_integer(String.slice(digits, 0, 2) || "0") >= 1 &&
String.to_integer(String.slice(digits, 0, 2) || "0") <= 12
end
defrx valid_cvv?(digits, is_amex) do
if(is_amex, do: String.length(digits) == 4, else: String.length(digits) == 3)
endNote: defrx bodies must be single expressions. Variable assignments like
len = String.length(digits) are not supported.
Imports defrx functions from another module.
The imported functions become available for use in rx() expressions
in the current module.
Example
defmodule MyApp.Validators do
use Lavash.Rx.Functions
defrx valid_email?(email) do
String.length(email) > 0 && String.contains?(email, "@")
end
end
defmodule MyAppWeb.UserLive do
use Lavash.LiveView
import Lavash.Rx
import_rx MyApp.Validators
calculate :email_valid, rx(valid_email?(@email))
endYou can also import only specific functions:
import_rx MyApp.Validators, only: [valid_email?: 1]
Captures a reactive expression at compile time.
The expression is stored as both source string (for JS transpilation)
and transformed AST (for server-side evaluation). Dependencies are
automatically extracted from @field references.
Examples
rx(length(@tags))
rx(@count * @multiplier)
rx(if @active, do: "on", else: "off")