I wonder if is there a way to auto generate form inputs in a loop.
I have an embedded schema with lot of checkbox fields and I I did this like that:
pe is the struct for this model passed as variable
<%= inputs_for f, :protective_equipment_value, fn p -> %>
<ul>
<%= for box <- Map.keys(@pe) do %>
<li>
<%= checkbox p, box %>
<%= label p, box %>
<%= error_tag p, box %>
</li>
<% end %>
</ui>
<% end %>
The only problem is that i have an additional id field which I can probably get rid of , and a second struct: true in this map - this needs a guard.
Is there maybe an official/less hacky way to do this??
Structs are just Maps with a special :__struct__ key pointing to the struct module it comes from.
My guess is that since Map.keys(struct) will return :__struct__ as one of the keys, you are generating an extra value in this form you don’t want.
Furthermore, the to_html helper is probably converting :__struct__ to "struct" and the module name (assuming it’s something like ProtectiveEquipmentValue) to a value of true when producing the form fields.
There are a few ways to make this easier for what you are trying to do. One I’ve used before is to define all defaults for structs in a module value, and create a keys function as well as a defstruct, like such:
defmodule ProtectiveEquipmentValue do
@defaults [my: nil, keys: nil, with: "default values"]
defstruct @defaults
def keys() do: @defaults |> Map.keys
end
Then in your form you can just loop over ProtectiveEquipmentValue.keys() instead.
Re-reading your description, you also have an extra unwanted :id field, as well as the :__struct__ one. It sounds like you’re using Map.keys/1 to extract map keys from an Ecto.Schema struct. You probably want to define a special list of form-friendly schema values somewhere, and iterate over that instead. For example:
defmodule ProtectiveEquipmentValue do
use Ecto.Schema
schema "protective_equipment_value" do
field :id, :uuid
field :name, :string
field :age, :integer, default: 0
has_many :posts, Post
end
def form_fields, do: [:name, :age]
end
Then iterate over ProtectiveEquipmentValue.form_fields instead.
I just wondered if there is maybe a special helper for this - this way I got the fields duplicated and I need to keep track of them in two places. I’ll use this solution thanks.
Since you can make any field name map to the primary database key, or even use a composite key as the primary key in some RDBMSs, I don’t think Ecto can ever know what parts of a schema are safe to present to users as editable input. You’ll have to specify it somewhere, eventually.