silviurosu
I struggle to figure out an issue with a form validation.
I have a phoenix liveview form that containts a nested model. I render the form like this:
<.simple_form for={@form} id="specialist_sign_up_job_form" phx-submit="submit_fields" phx-change="update">
....
<.inputs_for :let={adr} field={@form[:address]}>
<.input field={adr[:county]} type="select" id="address-county" label={gettext("Judet")} options={@counties} prompt={gettext("Alegeti judetul")} phx-change="load_cities" />
<.input field={adr[:city]} type="select" id="address-city" label={gettext("Oras")} options={@cities} prompt={gettext("Alegeti orasul")} />
<.input field={adr[:street]} type="text" id="address-street" parent_class="md:col-span-2" class="border border-brd text-gray-500 text-sm rounded-xl focus:ring-primary-600 focus:border-primary-600 block w-full px-3 py-4" label={gettext("Adresa")} phx-debounce="400" />
<.input id="address-id" field={adr[:id]} type="hidden" />
<.input id="address-country" field={adr[:country]} type="hidden" value={gettext("Romania")} />
<.input id="address-lat" field={adr[:lat]} type="hidden" />
<.input id="address-lng" field={adr[:lng]} type="hidden" />
</.inputs_for>
<./simple_form>
My model
defmodule Recenza.Models.Specialist do
schema "specialists" do
.......
belongs_to(:address, Address, foreign_key: :address_id)
end
def job_data_changeset(specialist, attrs, validate_required \\ true) do
ch =
specialist
|> cast(attrs, @job_allowed_fields)
|> maybe_validate_required_company(specialist)
if validate_required do
ch
|> cast_assoc(:address, required: true)
|> put_assoc(:speciality, parse_speciality(attrs), required: true)
|> validate_required(@job_required_fields)
|> geolocate_address()
else
ch
|> cast_assoc(:address)
|> put_assoc(:speciality, parse_speciality(attrs))
end
end
end
and the association model
defmodule Recenza.Models.Address do
......
def changeset(address, attrs) do
address
|> cast(attrs, @allowed_fields)
|> validate_required(@required_fields)
end
end
In PhenixLiveview process I am have this code:
def handle_event("submit_fields", %{"specialist" => specialist_params}, socket) do
user = socket.assigns.current_user
specialist = user.specialist
changeset = Specialist.job_data_changeset(specialist, specialist_params, true)
case Repo.insert_or_update(changeset) do
{:ok, specialist} ->
socket = assign(socket, :current_user, %User{user | specialist: specialist})
{:noreply,
socket
|> put_flash(:info, "specialist job data data saved")
|> push_navigate(to: ~p"/specialist_sign_up_services")}
{:error, changeset} ->
{:noreply, assign(socket, :form, to_form(changeset, as: :specialist))}
end
end
I am printing in console the form after each call to server side and the form attribute looks like this:
UDATED CHANGESET: #Ecto.Changeset<
action: :update,
changes: %{
address: #Ecto.Changeset<
action: :insert,
changes: %{country: "România"},
errors: [
street: {"can't be blank", [validation: :required]},
city: {"can't be blank", [validation: :required]},
county: {"can't be blank", [validation: :required]}
],
data: #Recenza.Models.Address<>,
valid?: false
>,
employment_status: "employee",
speciality: #Ecto.Changeset<
action: :insert,
changes: %{},
errors: [
name: {"can't be blank", [validation: :required]},
category_id: {"can't be blank", [validation: :required]}
],
data: #Recenza.Models.Speciality<>,
valid?: false
>
},
errors: [
description: {"can't be blank", [validation: :required]},
company_name: {"Compania este necesara pentru angajati", []}
],
data: #Recenza.Models.Specialist<>,
valid?: false
>
As you can see there are validation errors on base model and also on the association.
The problem is that the UI does not render the errors on the address, only on specialist:
This happens every time I complete any of the field from specialist. If I do not complete any field and just try to submit the form as is I can see the errors on the address too:
I spent a lot of time trying it figure this out but I could now. Can you guys give me any hint on what I am missing??
I guess it’s something related to fact that the form does not see the nested object as changed but I am stuck at this point
Trending in Questions
Other Trending Topics
Latest Phoenix Threads
Latest on Elixir Forum
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #blog-post
- #ai
- #elixirconf-us
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #hex
- #security
- #metaprogramming












Showing Posts 1 to 9- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
sodapopcan
I gave this a quick look. The main thing that sticks out is:
<.inputs_for />takes care of this. I’m not sure what kind of effect that would have have but you definitely shouldn’t include it.D4no0
Is there a reason you are using
adr[:county]instead ofadr.country? This makes it pretty hard to track down potential missing map keys.silviurosu
I tried to replace
add.countylike you said and I get this error:I used the same format as in the documentation.
silviurosu
I removed that hidden input for
address[:id]but it does not make any differencenseaSeb
Hello, do you have the required fields in @required_fields ?
|> validate_required(@required_fields)
sodapopcan
Interesting, ya I’m not sure. I notice you also have a duplicate
adr[:country]going on. You also don’t need to specify an fieldids manually as that is also taken care of you. That should really not make a difference but just grasping at straws here. Might need to see more code. Does it have anything to do with thatvalidate_requiredcheck (the variable one, not the function)? In one path you’re saying address is required and in the other you are not.silviurosu
I have added that param validate_required because it was validating the form even the first time it was displaying and I do not want that.
I am not sure what other code to share, I guess I shared whatever is relevant. I’ll try to debug it more
sodapopcan
The changeset will be shown as “invalid” but that’s ok, the errors won’t show in the UI on initial render. You definitely don’t need this.
silviurosu
I think I found the reason for the missing errors on UI.
The model I am starting with is this one:
As you can see the address association is empty at the moment.
The first change in the form calls “update” with these parameters:
nested address comes as a new empty map.
which transforms the Specialist changeset into this:
Address related model has been added in the changeset with the action
:insertIf I submit the form now and print in the logs the changeset before submit and after
Repo.insertI can see this:CHANGESET BEFORE SAFE:
CHANGESET AFTER SAVE:
between those two changesets, for Specialist action has changed from
nilto:updatebut for Address it’s the same:insertvsinsertFor Phoenix nothing changed in the address fields to show errors, I guess.
The hack I found it works for now it’s like this. When computing the changeset for the initial form instead of this:
I have change it to this:
It seems that for nested association I have to create an empty model when initializing the form.