Hello,
I am new to LiveView, Phoenix and Elixir, and I am struggling to populate the UI from the form contents. Here’s a simplified version of what I have in my code:
I have defined a struct with some simple fields:
defmodule MyApp.MyStruct do
defstruct some_integer: 3,
some_string: "",
some_bool: true
end
Then I have a context:
defmodule MyApp.Context do
alias MyApp.MyStruct
def current_struct() do
%MyStruct{}
end
end
It simply returns the newly created struct with default values. Now, I need to display a form populated with these values + allow modifying them. This is my _live.ex
file:
defmodule MyAppWeb.ViewLive do
alias MyApp.MyStruct
use MyAppWeb, :live_view
def mount(_params, _session, socket) do
{:ok, assign(socket, form: to_form(Map.from_struct(Context.current_struct())))}
end
# Here I have handle_event methods, but they don't do anything at the moment.
end
Finally, this is the .heex
file:
<div class="container mx-auto my-4">
<.form for={@form} phx-change="change_form" phx-submit="submit_form">
<!-- Number picker -->
<div class="mb-4">
<.label>I want to pick a number here:</.label>
</div>
<div class="flex items-center space-x-4 mb-4">
<label class="cursor-pointer">
<input type="radio" name="some_integer" value="3" class="hidden" checked={Context.current_struct().some_integer == 3}
/>
<span class={"px-4 py-2 rounded-md #{if Context.current_struct().some_integer == 3, do: "bg-gray-400", else: "bg-gray-200"} hover:bg-gray-400"}>
3 of something
</span>
</label>
<!-- More of these integer options -->
<!-- Checkbox -->
<div class="mb-4">
<.input
label="I'd like this to be true or false:"
type="checkbox"
value={Context.current_struct().some_bool}
field={@form[:some_bool]}
/>
</div>
<.button>Submit</.button>
</.form>
</div>
The code above kind of works now for initial values, but it stops working when I select 7 or 10 instead of 3. Note how to get the value or compute background colours I use Context.current_struct()
for calculations. I assume, that if I implement handle_event("change_form"...)
and modify my current_struct()
on each change and save it into the socket, then I could reference that saved struct in the heex template. But I would like to modify the actual struct only on submit, and in the meantime to get the data from the @form
. I tried to do that, but failed.
When I try to do something like
value={@form[:some_bool]}
the code crashes.
When I try to use input_value()
, then I always get nil, even if inspect(form)
shows that both some_integer
and some_bool
have the values that I expect them to have.
Please advise me how I can achieve this.