roganjoshua

roganjoshua

Basic Understanding of Live Form

I am trying to get a basic for to do my bidding.
I am very much a beginnner so many things are a bit cloudy.
I have a heex template below:

<main class="px-4 py-20 sm:px-6 lg:px-8">
  <.form for={@form} phx-change="validate" phx-submit="Go">
    <div class="p-2">
      <div>
        <.input
          name="version"
          field={@form[:version_id]}
          options={@versions}
          type="select"
          phx-change="select-version"
          value=""
          label="Select a Version"
        />
      </div>

      <div>
        <.input
          name="customer"
          field={@form[:customer_id]}
          options={[]}
          type="select"
          phx-change="select-customer"
          value=""
          label="Select a Customer:"
        />
      </div>
      <div>
        <.button>
          Go
        </.button>
      </div>
    </div>
  </.form>
  <pre><%= inspect assigns, pretty: true %></pre>
</main>

There are two <selects one is dependent on the other.
So the value selected from versions will populate the other selector with a list of customers that belong to that version.

The related code looks like this at the moment.

defmodule CustomerbuilderWeb.MainLive.Index do
  use CustomerbuilderWeb, :live_view

  alias Customerbuilder.Builder

  @impl true
  def mount(_params, _session, socket) do

    {:ok,
     socket
     |> assign(:versions, get_versions())
     |> clear_form()}
  end

  @impl true
  def handle_event("select-version", %{"id" => id}, socket) do
    {:noreply, stream(socket, :version_collection, id)}
  end

  @impl true
  def handle_event("select-customer", %{"id" => id}, socket) do
    {:noreply, stream(socket, :version_collection, id)}
  end

  def assign_form(socket, changeset) do
    assign(socket, :form, to_form(changeset))
  end

  def clear_form(socket) do
    form =
      socket.assigns
      |> to_form()

    assign(socket, :form, form)
  end

  defp get_versions() do
    for version <- Builder.list_version(), do: {version.name, version.id}
  end
end

Once the version and customer is set the Go button will take those values and send a POST request to an api (using HTTPPoison?) to kick off a build.

Then a kind of polling to api monitor the progress of the build to update the UI, which I haven’t even started.

a map with atom keys was given to a form. Maps are always considered parameters                                                      and therefore must have string keys, got: %{versions: [{"Version-8.6.2",1}, {"Version-8.6.1", 2}, {"Version-8.5.3", 3},

I am very grateful for any interest here.

Marked As Solved

codeanpeace

codeanpeace

The data set as assigns and/or streams in the server side socket isn’t transfered across the websocket. It’s the rendered HTML template and subsequent changes/diffs that get sent to the client side via the websocket.

defmodule LiveCalWeb.OrganizationUserSearchLive do
  use LiveCalWeb, :live_view

  # note: options are structured as a list of tuples representing `option` text and value
  # e.g. `["Admin": "admin", "User": "user"]` as described in the `Phoenix.HTML.Form.options_for_select/2` docs

  def mount(_params, _session, socket) do
    organization_options = for org <- get_organizations(), do: {org.name, org.id}

    {:ok,
     socket
     |> assign(:form, to_form(%{"organization_id" => nil, "user_id" => nil}))
     |> assign(:organization_options, organization_options)
     |> assign(:user_options, [])}
  end

  def handle_event("select-organization", %{"organization_id" => org_id} = form_params, socket) do
    user_options = for user <- get_organization_users(org_id), do: {user.name, user.id}

    {:noreply,
      socket
      |> assign(:form, to_form(form_params))
      |> assign(:user_options, user_options)}
  end

  def handle_event("submit", %{"organization_id" => organization_id, "user_id" => user_id}, socket) do
    IO.puts("~~ form submitted for organzation id: #{organization_id} and user id: #{user_id}~~")
    {:noreply, socket}
  end

  def render(assigns) do
    ~H"""
    <.form for={@form} phx-submit="submit">
      <.input field={@form[:organization_id]} phx-change="select-organization"
        type="select"
        label="First select an organization to load its users:"
        placeholder="organization"
        options={@organization_options}
        prompt="-- select organization --"
      />
      <.input field={@form[:user_id]}
        type="select"
        label="Now select an organization user:"
        placeholder="user"
        options={@user_options}
        prompt="-- select user --"
      />
      <button>Submit</button>
    </.form>
    """
  end

  # stubbed users and organizations
  defp get_organizations(), do: [%{id: 1, name: "OrgA"}, %{id: 2, name: "OrgB"}]
  defp get_organization_users(organization_id) do
    case organization_id do
      "1" -> [%{id: 1, name: "John from OrgA"}, %{id: 2, name: "Jules from OrgA"}]
      "2" -> [%{id: 3, name: "Jack from OrgB"}, %{id: 4, name: "Jill from OrgB"}]
    end
  end
end

# bonus: if you add `:let={f}` inside the `<.form ...>` component and `:if={f.params["organization_id"]}` inside the user `<.input ...>`, you can hide the user dropdown until an organization is selected

https://github.com/codeanpeace/live_cal/commit/300d7843a31f28a31678db0cf3dd81722656bec8

Also Liked

roganjoshua

roganjoshua

Appreciate the time and effort you have put in here @codeanpeace .

It really helps to see examples like this as I can piece together how it works by connecting the names of things.

Where Next?

Popular in Questions Top

hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
jononomo
For some reason my phoenix channels are working for me in my local dev environment, but as soon as I deploy via Docker, I get a 403 error...
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
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
fireproofsocks
Forgive me if this is obvious, but how does one delete a database record WITHOUT selecting it first? Ecto.Repo — Ecto v3.14.0 has exampl...
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
Patoshizzle
After calling mix ecto.create I get this error: 17:00:32.162 [error] GenServer #PID&lt;0.412.0&gt; terminating ** (Postgrex.Error) FATAL...
New

Other popular topics Top

vertexbuffer
Hello, can anybody help here..? I have a list of players and I what to delete an element, but every for loop the list is reverting to ori...
New
joaquinalcerro
Hi there, I am working with Ecto-Postgresql and I need to call all of the records from a specific table but the table has 40,000 records...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New
chrismccord
Phoenix 1.4.0 released Phoenix 1.4 is out! This release ships with exciting new features, most notably with HTTP2 support, improved deve...
688 31586 112
New
greenz1
I have a phoenix application from which a user can download multiple(5-6) files of size 1MB. I couldn’t find anything related to sending ...
New
saif
Hello everyone, Long time lurker first time poster here. I’ve recently begun working on Elixir full-time again! :raised_hands: It’s been...
New

We're in Beta

About us Mission Statement