sodapopcan

sodapopcan

New `to_form/2` in LiveView 1.18.2

I was wondering if there are any discussions around the new to_form/2 in LiveView 1.18.2. I’ve RTFM’d but there is just some dissonance in the change as it’s not mentioned in the changelog and it looks like we just need :let in nested inputs now? I am in no way complaining here, it’s def a step forward, it just caught me off guard and I’d love to know where I can follow along. Is the mailing list is best?

Thanks!

EDIT: I searched for to_form on the mailing list and found nothing.

Marked As Solved

LostKobrakai

LostKobrakai

The reason for the changes are meant to aid in LVs change tracking. Before the mentioned changes any update to the form would essentially rerender the whole form, that’s afaik meant to be gone/working better now.

Also Liked

mcrumm

mcrumm

Phoenix Core Team

Re: nested inputs, the addition of <Phoenix.Component.inputs_for> is one of the most recent changes. It replaces inputs_for() from Phoenix.HTML and it includes hidden inputs automatically (thanks @LostKobrakai :smiley:).

Here is a naive but complete example of rendering nested inputs:

# my_app_web/live/nested_live.ex
defmodule MyAppWeb.NestedLive do
  use MyAppWeb, :live_view

  defmodule Guestlist do
    use Ecto.Schema
    import Ecto.Changeset

    embedded_schema do
      field :event_name, :string

      embeds_many :guests, Guest do
        field :name, :string
      end
    end

    def changeset(form, params \\ %{}) do
      form
      |> cast(params, [:event_name])
      |> validate_required([:event_name])
      |> cast_embed(:guests, with: &guest_changeset/2)
    end

    def guest_changeset(guestlist, params) do
      guestlist
      |> cast(params, [:name])
      |> validate_required([:name])
    end
  end

  @impl Phoenix.LiveView
  def mount(_params, _session, socket) do
    guestlist = %Guestlist{
      event_name: "My New Event",
      guests: [
        %Guestlist.Guest{name: ""},
        %Guestlist.Guest{name: ""},
        %Guestlist.Guest{name: ""}
      ]
    }

    changeset = guestlist |> Guestlist.changeset()

    {:ok,
     socket
     |> assign(:guestlist, guestlist)
     |> assign_form(changeset)}
  end

  @impl Phoenix.LiveView
  def handle_event("change", %{"guestlist" => params}, socket) do
    changeset =
      socket.assigns.guestlist
      |> Guestlist.changeset(params)
      |> Map.put(:action, :validate)

    {:noreply, assign_form(socket, changeset)}
  end

  def handle_event("submit", %{"guestlist" => params}, socket) do
    case fake_save_guestlist(socket.assigns.guestlist, params) do
      {:ok, _guestlist} ->
        {:noreply,
         socket
         |> put_flash(:info, "Guestlist saved!")
         |> push_navigate(to: "/")}

      {:error, %Ecto.Changeset{} = changeset} ->
        {:noreply, assign_form(socket, changeset)}
    end
  end

  defp assign_form(socket, %Ecto.Changeset{} = changeset) do
    assign(socket, :form, to_form(changeset))
  end

  defp fake_save_guestlist(%Guestlist{} = guestlist, params) do
    guestlist
    |> Guestlist.changeset(params)
    |> Ecto.Changeset.apply_action(:save)
  end

  @impl Phoenix.LiveView
  def render(assigns) do
    ~H"""
    <.form for={@form} id="nested-form" phx-change="change" phx-submit="submit">
      <.input type="text" field={@form[:event_name]} label="Title" />
      <fieldset class="my-4">
        <legend class="py-2">Guests</legend>
        <.inputs_for :let={f_nested} field={@form[:guests]}>
          <.input type="text" field={f_nested[:name]} label={"Name #{f_nested.index + 1}"} />
        </.inputs_for>
      </fieldset>
      <.button type="submit">Submit</.button>
    </.form>
    """
  end
end

Note on LiveView v0.18.13 the <.form> component warns that for is a required attribute but it is not. Anyone should feel free to PR that change :slight_smile:

zachallaun

zachallaun

There have been a handful of pretty big new things popping up in LiveView without much fanfare, but if I were to guess, we’ll be hearing a lot more about these with the full Phoenix 1.7 release. Looking at the git history, to_form/2 landed just a few weeks ago. I’m just speculating, but given the sheer number of improvements present between Phoenix 1.7 and LiveView 0.18.*, I’d bet that the Phoenix team decided that it made the most sense to get things locked down and then release a mega-post/coordinated set of posts covering it all instead of drip-feeding for months.

sodapopcan

sodapopcan

Ya, I was thinking a lot about the documentation and what you’re describing. The quality is extremely good but searching hexdocs can be quite frustrating. I often can’t remember if something is in the guides or in the module docs and then, when it comes to Phoenix, what package it is in. I always use google or ddg to search hexdocs because there is no way to search across packages—at least no evident way, it’s very possible I’m missing something obvious. But overall the search is not great. For example, if you search “liveview” on the homepage it gives you five results, none of which are LiveView itself (I’m aware there are instructions below on how to jump to packages via the URL but that is not my point). Basically, when something changes or is added or removed, it’s not always evident where to look.

Where Next?

Popular in Questions Top

nobody
How to bind a phoenix app to a specific ip address? could not find anything about that, nowhere, unfortunately, but for me this is quite...
New
marius95
Hello everyone, I try to use an Javascript Event Handler in my root.html.leex file. Therefore I created a function in the app.js file: ...
New
Tee
can someone please explain to me how Enum.reduce works with maps
New
myronmarston
The Elixir Typespec docs show the following syntax for keyword lists in typespecs: # ... | [key: type] # keyword lists...
New
LegitStack
I’m trying to make a websocket server in Phoenix or raw Elixir. I heard about gun, I think I could use cowboy, but since I’m not that sma...
New
Lily
In templates/appointment/index.html.eex: &lt;%= for appointment &lt;- @appointments do %&gt; &lt;tr&gt; &lt;td&gt;&lt;%= appoi...
New
joeerl
Hello again - after a longish gap I’ve decided I really must dig into Elixir and see what’s been happening here - so I have a few questio...
New
Qqwy
Original source of discussion: This topic on the Pragmatic Programmers’ Functional Web Development with Elixir, OTP, and Phoenix forum. ...
New
sergio_101
I am VERY much an elixir newbie. I have taken one elixir course and one phoenix course on Udemy. During that course, I saw the instructor...
New
shijith.k
I am trying to start a new phoenix project with elixir 1.9, but mix phx.new does not work. It says that ** (Mix) The task "phx.new" could...
New

Other popular topics Top

New
AstonJ
Posting this to see if we can make things easier for people to get into Neovim. If you use Neovim and have a favourite distro please let ...
New
ovidiubadita
Hey all, I discovered Elixir and I love it. I always wanted to learn a functional programming and I intended to go for Haskell, but afte...
New
gausby
I asked this very same question on twitter and got some interesting feedback, but I thought it would be a good question to ask here as we...
1207 39467 209
New
vonH
When I run the Plug and I recompile I wind up having to use Ctrl C to quit iex and start again. Witht the help of rlwrap I can use the cu...
New
aalberti333
As the title describes, I’m trying to run Enum.map() over a list of key/value pairs, where the value is a map. My data looks like this: ...
New
axelson
This post is a wiki (feel free to hit the edit button near the bottom right of this post to add your own changes!) This post collects co...
239 48342 226
New
PeterCarter
There are pre-rolled solutions for other frameworks that do work. However, Phoenix does not seem to have these. Have people had good expe...
New
JakeBecker
TL;DR: I’ve just released an implementation of Microsoft’s IDE-independent Language Server Protocol for Elixir. It adds language support ...
1144 54120 245
New
lanycrost
Hi everyone! I need implement if…else if…else condition from my elixir code, and anymore of this control flow structures not work proper...
New

Latest on Elixir Forum

Elixir Forum

We're in Beta

About us Mission Statement