Firstly, thanks for the work put into LiveView!
I created a live form with LiveView and validations are working as expected, but I have a use case to set the value of a select field on the backend based on other changes (i.e. If XX value is added to an input, then change a select field value). The actual use case is when a customer is selected, the corresponding addresses fields are autopopulated in the other parts of the form.
I’ve tried setting the field to a different value using Changeset.put_change/3 and it works great for text_inputs but refuses to update select fields even though it’s reflected correctly in the changeset that is passed to the front end. In addition, I’ve tried using assign variables and passed them to the select input value, but it’s the same issue.
Below is a small example where on the handle_event(“validate”), the changeset changes are updated to gender: “Male” and username: “john_doe”. The username updates correctly, but the select input never updates on the frontend, even though if you inspect the changeset the changes are reflected properly.
Here’s the form:
<%= f = form_for @changeset, "#", [phx_change: :validate, phx_submit: :save] %>
<%= label f, :username %>
<%= text_input f, :username %>
<%= error_tag f, :username %>
<%= label f, :email %>
<%= text_input f, :email %>
<%= error_tag f, :email %>
<%= label f, :gender %>
<%= select f, :gender, ["Male", "Female"], prompt: "Select a gender" %>
<%= error_tag f, :gender %>
<%= label f, :phone_number %>
<%= text_input f, :phone_number %>
<%= error_tag f, :phone_number %>
<div>
<%= submit "Save", phx_disable_with: "Saving..." %>
</div>
</form>
<p><%= inspect @changeset %></p>
Here’s the LiveView:
...
def mount(_session, socket) do
{:ok,
assign(socket, %{
changeset: Accounts.change_user(%User{})
})}
end
def render(assigns), do: Phoenix.View.render(DemoWeb.UserView, "new.html", assigns)
def handle_event("validate", %{"user" => params}, socket) do
changeset =
%User{}
|> Demo.Accounts.change_user(params)
|> Ecto.Changeset.put_change(:gender, "Male")
|> Ecto.Changeset.put_change(:username, "john_doe")
|> Map.put(:action, :insert)
{:noreply, assign(socket, changeset: changeset)}
end
...
Using this code, if I start typing a phone number in the form, the username is auto set to john_doe based on the changeset, but the select input does not change to “Male” in this case.
Not sure if I’m doing something incorrectly or it’s an issue with LiveView or Morphdom.
Thanks for the help!