Reactive state management for Phoenix LiveView.
Lavash is two things in one package:
- A DSL (
Lavash.LiveView,Lavash.Component) for declaring state, computed values, forms, actions, and overlays, with a~Lsigil that auto-injects the client-side machinery for optimistic updates. - A reactive engine (
Lavash.Reactive,Lavash.LiveView.Explicit) that powers the DSL but is also usable directly from a plainPhoenix.LiveViewwhen you want the dependency graph without the rest.
See the README for a full guide. The minimal DSL example:
defmodule MyAppWeb.ProfileLive do
use Lavash.LiveView
state :user_id, :integer, from: :url, required: true
state :tab, :string, from: :url, default: "overview"
state :editing, :boolean, default: false
read :user, MyApp.Accounts.User do
id state(:user_id)
end
actions do
action :change_tab, [:tab] do
set :tab, rx(@tab)
end
end
render fn assigns ->
~L"""
<div>...</div>
"""
end
endImperative API
Inside a handler, when the declarative pipeline doesn't fit, use the imperative helpers:
def handle_event("save", %{"product" => params}, socket) do
socket =
socket
|> Lavash.set(:form_data, params)
|> Lavash.set(:submitting, true)
|> Lavash.finalize(__MODULE__)
# derived fields are now recomputed and assigns projected
{:noreply, socket}
end
Summary
Functions
Gets the full derived state map.
Gets a state or derived value from the socket.
Sets a state field value. This is for use in handle_event callbacks
when you need imperative control.
Gets the full state map (not including derived).
Updates a state field using a function.
Functions
Gets the full derived state map.
Finalizes state changes by recomputing dirty derived fields and projecting assigns.
Call this after using set/3 or update/3 in a handle_event.
Examples
def handle_event("save", params, socket) do
socket =
socket
|> Lavash.set(:form_data, params)
|> Lavash.set(:submitting, true)
|> Lavash.finalize(__MODULE__)
# Now derived fields are recomputed and assigns are projected
{:noreply, socket}
end
Gets a state or derived value from the socket.
Examples
changeset = Lavash.get(socket, :changeset)
form_data = Lavash.get(socket, :form_data)
Sets a state field value. This is for use in handle_event callbacks
when you need imperative control.
Note: This does NOT automatically recompute derived fields or project assigns.
Call Lavash.finalize/2 after all updates to trigger recomputation.
Examples
socket = Lavash.set(socket, :form_data, params)
socket = Lavash.set(socket, :submitting, true)
socket = Lavash.finalize(socket, __MODULE__)
Gets the full state map (not including derived).
Updates a state field using a function.
Examples
socket = Lavash.update(socket, :count, &(&1 + 1))