BLacika
Liveview Form - Update other fields on phx-change
Hi!
I would like to ask for help. I have a form and I would like to change the values of some fields if I change one of them.
For example, I have this code snippet:
@impl true
def handle_event("validate", %{"_target" => ["invoice", "date"], "invoice" => invoice_params}, socket) do
%{"date" => date} = invoice_params
invoice = %{
socket.assigns.invoice
| due_date: Date.add(Date.from_iso8601!(date), socket.assigns.invoice.payment_term),
date: Date.from_iso8601!(date)
}
changeset =
invoice
|> Invoices.change_invoice(invoice_params)
|> Ecto.Changeset.put_assoc(:invoice_lines, invoice.invoice_lines)
|> Map.put(:action, :validate)
{:noreply,
socket
|> assign(:invoice, invoice)
|> assign(:changeset, changeset)}
end
I want to update the due_date field. But this does not change the field in the form.
I’ve manually updated the socket.assigns.invoice, it doesn’t work either.
I have a partner field which works though. When I select a partner, it goes through a few updates. The problem there is that the validation on the other field (date) does not work. Here is the code for that:
@impl true
def handle_event(
"validate",
%{"_target" => ["invoice", "partner_id"], "invoice" => %{"partner_id" => partner_id}} = invoice_params,
socket) when partner_id != "" do
partner = Partners.get_partner!(partner_id) |> Repo.preload([:bank_accounts])
invoice = %{
socket.assigns.invoice
| partner_id: partner.id,
payment_method: partner.payment_method,
payment_term: partner.payment_term,
currency_id: partner.currency_id,
due_date: Date.add(socket.assigns.invoice.date, partner.payment_term),
exchange_rate: exchange_rate(partner.currency_id)
}
changeset = invoice_changeset(invoice, invoice_params) |> Map.put(:action, :validate)
{:noreply,
socket
|> assign(:partner, partner)
|> assign(:invoice, invoice)
|> assign(:partner, partner)
|> assign(:changeset, changeset)
|> assign(:bank_accounts, bank_accounts(partner.bank_accounts))}
end
Is there anything in the documentation about this, or perhaps an example? I have not found anything similar here on the forum. Thank you! ![]()
Marked As Solved
codeanpeace
Ahh, I think you may be overwriting the due date in your callback function.
The form’s current due_date is being sent back in the parameters nested under "invoice".
This means that the invoice_params from the callback function head includes the "due_date" coming from the form. Assuming Invoices.change_invoice/2 function is pretty standard, the form’s "due_date" in the invoice_params will replace the due_date in the invoice struct that you calculated and defined in the function itself.
Also Liked
BLacika
Thank you very much for your help and guidance. You helped a lot
It finally helped me to find out where I went wrong. Basically, I should have read the documentation better
The thing is, I thought that socket.assigns.invoice reflected the state of the form and I started to update it. I rewrote the code and now I update the params fields from the form and compile the changeset that way. So now it works as I had intended.
Like here:
@impl true
def handle_event("validate", %{"_target" => ["invoice", "date"], "invoice" => invoice_params}, socket) do
%{"date" => date, "payment_term" => payment_term} = invoice_params
invoice_params =
invoice_params
|> Map.put("due_date", Date.add(Date.from_iso8601!(date), String.to_integer(payment_term)))
|> Map.put("date", Date.from_iso8601!(date))
changeset =
socket.assigns.invoice
|> Invoices.change_invoice(invoice_params)
|> Ecto.Changeset.put_assoc(:invoice_lines, socket.assigns.invoice.invoice_lines)
|> Map.put(:action, :validate)
socket =
socket
|> assign(:changeset, changeset)
{:noreply, socket}
end
codeanpeace
Hmm, what does your HEEX code look like?
And as a sanity check, could you add an IO.inspect(changeset, label: "changeset: ") and post the console output? It also might be worth setting liveSocket.enableDebug() and sharign what comes through in your browser’s developer console.
trisolaran
This might be a long shot, but could it be that the element in the form whose value you want to update is the one having focus? Because in that case LiveView would never overwrite the value entered by the user.
Popular in Questions
Other popular topics
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
- #channels
- #elixirconf
- #exunit
- #discussion
- #code-sync
- #javascript
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance








