kccarter
How to correctly use .form component with a Map?
We’re trying to create a form using the .form component and a map but unable to figure out the right combination. We are not using Ecto. Our data is unstructured JSON stored in a NoSQL backend.
The documentation says to use to_form with a map, but we keep getting stuck with the error that the given map does not implement HTML.Safe.
<.form :let={f} for={@account} action={~p"/accounts/#{@tag["id"]}"}>
# We know there's always a name, but in reality
# this is a for-loop over the account's keys.
<.input field={f["name"]} />
</.form>
defmodule DemoWeb.AccountsController do
def edit(conn, %{"id" => id}) do
# This returns a Map of arbitrary key/value pairs.
account = Accounts.find!(id)
# Is this what we're supposed to do?
account_form = Phoenix.Component.to_form(account)
render(conn, :edit, account: account_form)
end
end
Our goal is to just render a form for a map, and then have the form fields posted back to the appropriate endpoint, where we’ll convert it back to a JSON blob and store it accordingly. Ecto, and Ecto changesets, are not used anywhere.
Most Liked
sodapopcan
You’re making a similar mistake that I made—they are using controllers, not LiveViews. to_form just doesn’t work with controllers (from the bit of testing I did). And because of this it doesn’t really matter if they use :let or not (I also had the same thought, though).
kccarter
Yeah, in a framework with relatively good documentation, we’ve found the narrative around forms to be a bit confusing and hard to follow. We’re not using LiveView, so the fact that .form is part of Phoneix.LiveView initially made us look past it.
There’s form_for in Phoenix.HTML but this blog post suggests that it’s now deprecated. And this older forum post has a post from Jose saying that .form is the correct way to go, but as noted above we initially thought that was just for LiveViews.
In core_components.ex there’s .simple_form which is used throughout the generated scaffolding code. In this case you can quickly see it just calls through to .form, but when you’re initially learning it’s an added layer of indirection.
In our case, where we’re just using a plain Map, the “secret” attribute to make it work was as:.
We’re editing JSON records with an arbitrary and unknown set of keys. All we really want a form component for is to have the proper _method and _csrf attributes injected along with proper field naming.
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








