Arsenalist
Showing form fields conditionally base on radio input value
I want to show input fields based on the value of a the radio button. Here are the two approaches I tried. This is inside a LiveComponent and I’m on LiveView 1.0.2. What is the best way to implement this simple feature (neither of the below work)?
APPROACH 1
When I click on a radio button, it is selected, but none of the following two ifs evaluate to true so the additional fields are never shown.
<.form for={@form} phx-change="validate" phx-submit="save" phx-target={@myself}>
<.input
label="I am an individual"
type="radio"
value="INDIVIDUAL"
field={@form[:entity_type]}
/>
<.input
label="I represent a company"
type="radio"
value="COMPANY"
field={@form[:entity_type]}
/>
<%= if Phoenix.HTML.Form.input_value(@form, :entity_type) == "INDIVIDUAL" do %>
<.input label="First Name" type="text" field={@form[:first_name]} />
<.input label="Last Name" type="text" field={@form[:last_name]} />
<% end %>
<%= if Phoenix.HTML.Form.input_value(@form, :entity_type) == "COMPANY" do %>
<.input label="Company Name" type="text" field={@form[:company_name]} />
<% end %>
</.form>
Here is the LiveView code:
def mount(socket) do
form_attributes = %{
"first_name" => "",
"last_name" => "",
"company_name" => "",
"entity_type" => ""
}
{:ok,
assign(
socket,
:form,
to_form(form_attributes)
)
}
end
def handle_event("validate", _params, socket) do
{:noreply, socket}
end
APPROACH 2
After not getting this to work I also tried this approach where I set a new variable to track which entity_type is selected. This resulted in the if condition being executed, but the radio button not being selected and I have to click it again for it to be selected. Here’s a video: Area - Dubz
<.form for={@form} phx-change="validate" phx-submit="save" phx-target={@myself}>
<.input
label="I am an individual"
type="radio"
value="INDIVIDUAL"
field={@form[:entity_type]}
phx-change="entity_type_changed"
phx-target={@myself}
/>
<.input
label="I represent a company"
type="radio"
value="COMPANY"
field={@form[:entity_type]}
phx-change="entity_type_changed"
phx-target={@myself}
/>
<%= if @entity_type_selected == "INDIVIDUAL" do %>
<.input label="First Name" type="text" field={@form[:first_name]} />
<.input label="Last Name" type="text" field={@form[:last_name]} />
<% end %>
<%= if @entity_type_selected == "COMPANY" do %>
<.input label="Company Name" type="text" field={@form[:company_name]} />
<% end %>
</.form>
def mount(socket) do
form_attributes = %{
"first_name" => "",
"last_name" => "",
"company_name" => "",
"entity_type" => ""
}
{:ok,
assign(
socket,
:form,
to_form(form_attributes)
)
|> assign(:entity_type_selected, "")
}
end
def handle_event("entity_type_changed", %{"entity_type" => entity_type} = params, socket) do
{:noreply, assign(socket, :entity_type_selected, entity_type)}
end
First Post!
garrison
When your "validate" event is called, the form sends back the params in the params variable (the second argument to handle_event/3). You have to actually assign the new values back to the socket - currently you are just throwing them away.
{:noreply, assign(socket, :form, to_form(params))}
This is why your first approach doesn’t work. It’s also why your second approach doesn’t work - you are updating the variable, but you’re also throwing away the new params, so when the update comes back from the server it clobbers the radio button (since the server state was never changed).
Most Liked
LostKobrakai
The form abstraction needs to deal with invalid and partial values and various types of values. Hence it’s not the best place to check if an input is of a certain value. I’d suggest checking Ecto.Changeset.get_field(@form.source, field) instead if the form is based on a changeset.
Last Post!
sreyansjain
You can try this. I am on mobile so I am a bit limited now.
<.input
label="I am an individual"
type="radio"
value="INDIVIDUAL"
field={@form[:entity_type]}
checked={@form[:entity_type].value && @form[:entity_type].value == "INDIVIDUAL"}
/>
For conditional field visibility this would work too
<.input :if={@form[:entity_type].value && @form[:entity_type].value == "INDIVIDUAL"} label="First Name" type="text" field={@form[:first_name]} />
Need to update the form in the validate event
def handle_event("validate", params, socket) do
{:noreply, assign(socket, :form, to_form(params))}
end
Trending in Questions
Other Trending 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
- #elixirconf-us
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #metaprogramming
- #security
- #hex









