DestroyedSoul
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.
Trending in Questions
Other Trending Topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #library
- #deployment
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #elixirconf
- #channels
- #exunit
- #discussion
- #code-sync
- #podcasts
- #javascript
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #ai
- #elixirconf-us
- #blog-post
- #elixir-ls
- #phoenix_html
- #iex
- #graphql
- #genstage
- #websockets
- #supervisor
- #advent-of-code
- #distillery
- #processes
- #api
- #forms
- #elixirconf-eu
- #metaprogramming
- #hex











Showing Posts 1 to 6- Show Best Posts
- Show All (oldest first)
- Show All (newest first)
benwilson512
Hi @DestroyedSoul welcome! Whenever you have an error, please always post the full error and stacktrace so that we don’t have to guess what it is.
DestroyedSoul
Hello,
The error was something about not implemented Safe protocol. Basically, FormField is not a type you could assign to
value.But this is not the primary thing here, I mentioned that for “history”. The main question is how to extract a value for the field.
codeanpeace
Correct, if you really wanted to manually access the
valueof aPhoenix.HTML.FormFieldstruct, you have to do something like@form[:some_bool].value.Note that since you’re using the default
.inputfunctional component, you don’t need to manually specify thevaluehere as it’s automatically derived from thePhoenix.HTML.FormFieldpassed viafield={@form[:some_bool]}– see below.DestroyedSoul
This is exactly where the problem is: the
valueis always nil.sodapopcan
Hiya and welcome!
It’s a bit hard to know for sure what is wrong without the exact code—for example, if
Context.current_struct()is always returning a new struct (ie, without getting it from a database or something), thenContext.current_struct().some_integeris always going to3, even if you update the struct.Another problem I see is that you are doing
Map.from_structwhich will return a map with atom keys. In order to use a map with a form, you need to use string keys. The console should be giving you a warning about this, though it’s easy to miss. Once you’ve done this, then@form[:field].valuewill work (note it’s an atom key in this case). As @codeanpeace noted, when using the<.input />component then you don’t need to do this and you should remove thevalueattribute. In the case of the radio button that is using a raw html input, you will need to do this.In your change handler, the updated fields will come through
paramswhich you can then construct into a new map, convert it to a form, and store that new form inassigns.I should clarify I don’t have much experiencing using forms with raw maps beyond simple experimentation. They are much easier (and safer) to use with changesets.
DestroyedSoul
The
string keysis what seemed to be a problem here.