ecode_nntt

ecode_nntt

How to create a nested form implementation using ash framework

I want to implement a view for teachers so they can add their students. It will be just a form containing name, age. and a add student button when the teacher clicks it shall add another form underneath the first and she can add as many as they can but the trick that every field shall have its own validations and then the render submit they will all be saved in the db.

    attributes do
      uuid_primary_key(:id)
  
      attribute :email, :ci_string do
        allow_nil?(false)
        public?(true)
      end
  
      attribute :hashed_password, :string do
        allow_nil?(false)
        sensitive?(true)
      end
  
      attribute :age, :string do
        allow_nil?(false)
      end
  
      attribute :full_name, :string do
        allow_nil?(false)
      end
      
      create_timestamp(:inserted_at)
      update_timestamp(:updated_at)
    end

these are my attributes in the resource file and i also created the action create that i’ll be using while submitting and it works but with only one field which is the first one

      defp render_step(1, assigns) do
        ~H"""
         <div class="flex flex-col flex-1">
          <%= for {student, index} <- Enum.with_index(@students) do %>
          <.live_component
            id={"students_form_add_#{index}"}
            module={Myapp.Students}
            student={student}
            changeset={@changeset}
          />
         <% end %>
          <button phx-click="add_student" class="border border-[#121212] rounded-lg 
     flex flex-row gap-2 py-1.5 px-3 cursor-pointer w-1/5 mt-4">
              <img src="/images/pluss.svg">
              <p class="text-sm text-nowrap"> <%= gettext("Add another student") %> 
            </p>
          </button>
        </div>
        """
      end

        @impl true
        def mount(_params, _session, socket) do
          {:ok,
           socket
           |> assign(students: [%{name: "", age: ""}]) 
           |> assign(
   changeset:
     Myapp.Accounts.Student
     |> AshPhoenix.Form.for_create(:create, forms: [auto?: true])
     |> to_form()
          )
          }
        end

      @impl true
      def handle_event("validate_students", %{"form" => params}, socket) do
        changeset = AshPhoenix.Form.validate(socket.assigns.changeset, params)
        {:noreply, assign(socket, changeset: changeset)}
      end

this render step, mount and the validation are in the liveview and the actual form is in a live_component because i was trying to loop over the live_component itself

        def render(assigns) do
          ~H"""
          <div class="flex flex-col flex-1 ml-5">
          <.form id="student_form" phx-change="validate_students" phx- 
     submit="save_students">
          <div class="flex space-x-4 items-center mb-4">
          <div class="mt-4 flex-1">
          <.input type="text" field={@changeset[:name]} label="Name" class="border-0 
   mt-1 block w-full focus:ring-[#FAFAFA] border border-[#FAFAFA] bg-[#FAFAFA] 
  rounded-lg px-2 py-3" placeholder="--"  />
          </div>
              <div class="mt-4 flex-1">
                <div class="relative">
                <.input type="text" field={@changeset[:age]} label="Age" class="border-0 
  mt-1 block w-full focus:ring-[#FAFAFA] border border-[#FAFAFA] bg-[#FAFAFA] 
  rounded-lg px-2 py-3" placeholder="--"  />
                <div class="absolute inset-y-0 pl-3 flex items-center">
                  </div>
                </div>
              </div>
          </div>
      
          <div class="flex justify-end gap-2 " id="buttons">
            <button  phx-click="previous_step" class="flex bg-[#F7F7F7] text-black px-4  
    py-2 mt-4 rounded-md items-end rounded-xl"> <%= gettext("Previous") %> 
  </button>
            <button
                type="submit"
                class="flex bg-[#1E1E20] text-white px-4 py-2 mt-4 rounded-md items-end 
   rounded-xl disabled:bg-gray-400 disabled:cursor-not-allowed"
                >
                Save student
               </button>
                </div>
          </.form>
            </div>
          """
        end  

and this is the render in the live component. Can please anyone tell me how could i implement this specially the validation part. the for loop over the livecomponent it does add a form underneath the first however when I write in one it writes in all inputs with the same name.

First Post!

zachdaniel

zachdaniel

Creator of Ash

The described sort/drop/add params are not yet released, but this new guide should still be of use. I plan on releasing it next week: New tools, and a new guide on nested forms with `AshPhoenix.Form`!

Where Next?

Popular in Questions Top

qwerescape
Is there a way to get the call stack or stack trace at any point in the code? Not from exceptions, but an expression that returns how the...
New
mgjohns61585
Could someone help me? I’m making my first elixir program, number guessing game. I can’t figure out how to convert the user’s guess from ...
New
shahryarjb
Hello, I have map which I want to convert it to string like this: the map: %{last_name: "tavakkoli", name: "shahryar"} the string I ne...
New
stefanchrobot
What’s the safe way to decode a JSON string into a struct? I want to avoid calling String.to_atom. Jason.decode can give me a map with st...
New
hariharasudhan94
lets say i have a sample like a = 20; b = 10; if (a &gt; b) do {:ok, "a"} end if (a &lt; b) do {:ok, b} end if (a == b) do {:ok, "equa...
New
fayddelight
I tried installing elixir 1.11.2 erlang 23.3.4 via asdf in my zsh shell. Enabled the versions locally and globally. When I list them ...
New
bsollish-terakeet
Credo is smart enough to check for (something like) this: assert length(the_list) == 0 with this response: Checking if an enum is empt...
New
romenigld
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
nsuchy
Hi. I’ve noticed that Windows Powershell has it’s own IEX command and you cannot access Elixir’s IEX due to the conflict. This isn’t a cr...
New
hariharasudhan94
I would like to know what is the best IDE for elixir development?
New

Other popular topics Top

Darmani72
If I have a post route which an argument: post /my_post_route/:my_param1, MyController.my_post_handler How would get the post params ...
New
senggen
Erlang/OTP 25 [erts-13.2.2] [source] [64-bit] [smp:8:8] [ds:8:8:10] [async-threads:1] 15:22:35.803 [error] gen_event {lager_file_backend...
New
jononomo
I am trying to figure out how Mix knows whether the environment is test, dev, or prod – where is this set? Thanks.
New
aesmail
Hello guys, I have finally made it. I created an admin interface for a framework. It’s been on my todo list for years and with the curre...
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
rms.mrcs
Hi, I need to transform a list of numbers into a map where the keys are the indexes and the values are the original values of the list. ...
New
romenigld
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
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
WestKeys
Currently suffering from paralysis by [HTTP client] analysis. This is rather unusual in Elixirland as there tends to be consensus on the ...
New
sergio
Kind of like when jquery came out, it was super necessary. Existing drag and drop libraries have a bunch of baggage to support old browse...
New

We're in Beta

About us Mission Statement