zachdaniel
Creator of Ash
New tools, and a new guide on nested forms with `AshPhoenix.Form`!
Working with nested forms in Ash was already great, but it’s even better now with a the new features that will be in the next release of AshPhoenix! Use hidden checkboxes to automatically add, remove and reorder nested forms!
Also check out the new guide. Inspired by Phoenix & Ecto’s drop_param and sort_param, but with no need to configure a drop_param or sort_param, all automatically handled by AshPhoenix.Form
Example code:
defmodule MyApp.MyForm do
use MyAppWeb, :live_view
def render(assigns) do
~H"""
<.simple_form for={@form} phx-change="validate" phx-submit="submit">
<.input field={@form[:email]} />
<!-- Use sortable.js to allow sorting nested input -->
<div id="location-list" phx-hook="Sortable">
<.inputs_for :let={location} field={@form[:locations]}>
<!-- inputs each nested location -->
<div data-sortable="true">
<!-- AshPhoenix.Form automatically applies this sort -->
<input
type="hidden"
name={"#{@form.name}[_sort_locations][]"}
value={location_form.index}
/>
<.input field={location[:name]} />
<!-- AshPhoenix.Form automatically removes items when checked -->
<label>
<input
type="checkbox"
name={"#{@form.name}[_drop_locations][]"}
value={location_form.index}
class="hidden"
/>
<.icon name="hero-x-mark" />
</label>
</div>
</.inputs_for>
<!-- AshPhoenix.Form automatically appends a new item when checked -->
<label>
<input
type="checkbox"
name={"#{@form.name}[_add_locations]"}
value="end"
class="hidden"
/>
<.icon name="hero-plus" />
</label>
</div>
</.form>
"""
end
def mount(_params, _session, socket) do
{:ok, assign(socket, form: MyApp.Operations.form_to_create_business())}
end
def handle_event(socket, "validate", %{"form" => params}) do
{:noreply, assign(socket, :form, AshPhoenix.Form.validate(socket.assigns.form, params))}
end
def handle_event(socket, "submit", %{"form" => params}) do
case AshPhoenix.Form.submit(socket.assigns.form, params: params) do
{:ok, business} ->
socket =
socket
|> put_flash(:success, "Business created successfully")
|> push_navigate(to: ~p"/businesses/#{business.id}")
{:noreply, socket}
{:error, form} ->
{:noreply, assign(socket, :form, form)}
end
end
end
It also comes with very useful tools for manually managing nested forms, when checkboxes just won’t cut it ![]()
def handle_event("add-form", %{"path" => path}, socket) do
form = AshPhoenix.Form.add_form(socket.assigns.form, path, params: %{
address: "Put your address here!"
})
{:noreply, assign(socket, :form, form)}
end
def handle_event("remove-form", %{"path" => path}, socket) do
form = AshPhoenix.Form.remove_form(socket.assigns.form, path)
{:noreply, assign(socket, :form, form)}
end
def handle_event("update-sorting", %{"path" => path, "indices" => indices}, socket) do
form = AshPhoenix.Form.sort_forms(socket, path, indices)
{:noreply, assign(socket, form: form)}
end
def handle_event("move-up", %{"path" => form_to_move}, socket) do
# decrement typically means "move up" visually
# because forms are rendered down the page ascending
form = AshPhoenix.Form.sort_forms(socket, form_to_move, :decrement)
{:noreply, assign(socket, form: form)}
end
def handle_event("move-down", %{"path" => form_to_move}, socket) do
# increment typically means "move down" visually
# because forms are rendered down the page ascending
form = AshPhoenix.Form.sort_forms(socket, form_to_move, :increment)
{:noreply, assign(socket, form: form)}
end
Happy Friday folks! ![]()
Most Liked
sevenseacat
Author of Ash Framework
Chapter 8 will cover nested forms - editing an album and all of the tracks for an album in one form. That should be out in a few weeks ![]()
2
Popular in News & Updates
Hey folks! We’ve just released the beta 0.1.0 version of ash_sqlite. Take a look at the guide here: https://hexdocs.pm/ash_sqlite/get-sta...
New
What if you had full stack types for SPAs built with tech like React, Inertia, Vue, Svelte… but all of the power Ash Framework and Elixir...
New
This week we added official Nerves support for the OSD32MP1 line of SOMs.
Currently we have tested the osd32mp1-brk breakout board, and ...
New
Had a great time at Jax.Ex! Gave a talk called “Model your Domain, Derive the Rest”. Thanks to the folks at HashRocket for having me!
New
Backward Incompatible Changes
Change template sigil from ~H to ~HOLO
Require Elixir 1.15+ and Erlang/OTP 24+
New Features
Add “select”...
New
I know you might be thinking ¬
“Why make another SSH daemon wrapper when there already exists many like sshex and esshd??”
Well, grea...
New
NervesPack 0.4.0 is a minor bump with a fairly big change.
This update drops :nerves_firmware_ssh in favor of the newer and more focused...
New
We’re excited to announce that we’re actively working on NervesHub 2.0, an improved version of our IoT device firmware update and managem...
New
Nerves systems provide the operating system, libraries and other tools for building firmware for specific hardware. The Nerves Core Team ...
New
We’ve released new versions of all of the officially maintained Nerves Systems. The official systems, nerves_system_rpi0, nerves_system_b...
New
Other popular topics
I am using the Starship cross-shell prompt – it seems pretty nice, but I get some errors:
[WARN] - (starship::utils): Executing command ...
New
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
New
How to handle excepions in elixir? Suppose i have A, B, C ,D, E modules. and each module has get() function. A.get() method will call th...
New
In the Dialyzer docs ( http://erlang.org/doc/man/dialyzer.html#requesting-or-suppressing-warnings-in-source-files ), there is a way to tu...
New
I am trying to run a deploy with docker and I successfully runned with this command:
docker build -t romenigld/blog-prod .
but when I t...
New
Hello everybody,
usually, I use a 29" ultra-wide monitor for VSCode which can easily accomodate explorer (files panel) + file with code ...
New
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? https://hexdocs.pm/ecto/Ecto.Repo.h...
New
I will often find my self writing things similar to:
case some_value do
nil -> something()
"" -> something()
_ -> someth...
New
To my knowledge, put_in, Map.update etc. all have the one limitation of not automatically creating intermediate keys when needed (for exa...
New
Elixir appears to be a superior language to Python. I don’t see any advantage of Python over Elixir. Are there any?
New







