I’m trying to allow a user to add tags to a parent using a has_many relationship. I’d like to offer ‘suggested’ tags that they can click and these are added to the form data. These are simple, single, text-entry forms.
I have a dynamic form using inputs_for with a button to add new, blank, form entries and remove existing values, per the standard Liveview documentation. I can add new tags, which is a single input, and this works as expected.
How can I programatically add new inputs_for entries with data in the form entry?
Can I use the value=“new” to set a value I can capture instead?
I’ve tried putting suggested tags as buttons with phx-click and handlers to capture the suggested tag value and put them in the parent struct as a struct item rather than param map, but I can’t work out how to have these render in the inputs_for in the same way as the ‘new’ tags.
That link was great and well written. Thanks! Now all working.
The trick in the link above to get the form data and update the changeset in a handler that doesn’t receive the form params, using get_assoc/put_assoc, worked great. I can keep all the existing code & behaviour the same, so a neat bonus is still getting deletion of dynamic inputs for ‘free’ from drop_param.
So to programatically add new inputs with data, you just need a button with a value and one additional handler:
Then I use a dedicated changeset function header to handle the add-case
def changeset(entity, %{"sort_param" => [initial_attrs]} = attrs) do
initial_relation_attrs = JSON.decode!(initial_attrs)
entity
|> cast(attrs, [])
|> cast_assoc(:relation, sort_param: :sort_param, with: &MyRelation.changeset(&1, &2, initial_relation_attrs)
end
def changeset(entity, attrs) do
# handle other change
end
An last but not least I use a dedicated changeset function header to handle changing the relation:
def changeset(relation, %{"_existing_relation" => _} = attrs, _initial_attrs) do
# we can ignore initial_attrs for this changeset since this is an existing relation
...
end
def changeset(relation, _attrs, initial_attrs) do
# attrs is always empty when adding, use initial_attrs instead to build the changeset
...
end
Hope this helps anyone who might find this post later