Bug when controlling input in LiveView

Hi! I’m using LiveView to automatically generate slugs based on a form’s “Name” field. We do this by calling put_change on the changeset inside the phx-change callback.

This works perfectly for “new” forms, but on “edit” forms, there is an interesting bug:

The issue seems to be when we put_change, Ecto compares the value to the existing value in the data, and since it matches the original value, it’s removed completely from the changes, e.g.

#Ecto.Changeset<
  changes: %{
    name: "Origina",
    slug: "origina",
  },
>
#Ecto.Changeset<
  changes: %{
    name: "Original",
  },
>

But LiveView seems to try to hold on to the current state in the form rather than falling back to the data, and gets stuck on the previous version. Is there a way to fix this?

How are you showing the disabled slug input field? I think using

text_input(form, :slug, disabled: true)

should work. If you’re using Ecto.Changeset.get_change/3, you can switch to using Ecto.Changeset.get_field/3.

You can use force_change to have ecto not care if there was an actual change.

1 Like

Thank you @LostKobrakai, that’s just what I need!

I also found it’s not LiveView’s fault: the old slug actually hangs around changeset.params. And input_value is preferring the params version over the data version.