zachdaniel

zachdaniel

Creator of Ash

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 :sunglasses:

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

:partying_face: :hugs: Happy Friday folks! :hugs:

Showing Posts 1 to 3

Chrichton

Chrichton

I this feature already available?

I would like to modify an ash generated “many form” from the new Ash PragPro book:
One Artist has many Albums

  • Display the Albums when showing an Artist
  • Create/Select Albums, when creating a new Artist
  • Modify Albums of a selected Artist.

Thanks for your reply, Heiko

sevenseacat

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 :slight_smile:

zachdaniel

zachdaniel OP

Creator of Ash

It is released, yes.

— All posts loaded —

Where Next? Top

Trending in News & Updates Top

pcharbon
:heart::heart::heart::heart::heart::heart::heart::heart::heart::heart::heart::heart::heart::heart::heart::heart::heart::heart::heart::hea...
New
nature
NatureWhistle v0.4.1 is out! :tada: This release is a pretty significant step forward for the project. When I first built NatureWhistle,...
New
webofbits
Aludel 0.7.0 is released :tada: Since 0.5.0, Aludel has grown into a much more complete LLM evaluation toolkit for Elixir and Phoenix app...
New

Other Trending Topics Top

JesseHerrick
Hey, I’m Jesse and I’m the main contributor behind Dexter, a full-featured, lightning-fast Elixir LSP optimized for large codebases. It s...
New
marciok
Hi there! We created Gust: A task orchestrator inspired by Airflow. For those who have never heard about Aiflow, it’s a Python-based wor...
New
mhanberg
Hi everyone! The first release candidate for the Expert language server project is now available! We’ve published a press release detai...
New
jimsynz
Beam Bots (or just BB for short) is a framework for building fault-tolerant robotics applications in Elixir using familiar OTP patterns. ...
New
Dmk
Xamal is a deployment tool for Elixir apps that deploys native releases to bare metal servers over SSH. It’s a port of GitHub - basecamp/...
New
webofbits
With AI doing more of the implementation work, I’ve been wondering how much coding I should deliberately keep doing myself. My main conc...
#ai
New

We're in Beta

About us Mission Statement

Options

Thread Display Mode




Thread Preview

Skip Thread Previews