When working with Ecto in Elixir, you often update a changeset using Ecto.Changeset.put_change/3
. But in some cases — especially in Phoenix LiveView forms — you might notice that a change doesn’t "stick" if the value hasn’t actually changed from the original. That’s where force_change/3
comes in.
Let’s take a look at the difference and when you should use each.
put_change/3
: the smart setter
put_change(changeset, :field, value)
- Adds the field to
changes
only if the newvalue
is different from what's inchangeset.data
. - If the value is equal to the original, no change is recorded.
- Ideal for avoiding unnecessary updates (e.g., in database writes).
Example:
changeset = put_change(changeset, :title, "My Title")
If changeset.data.title
is already "My Title"
, this won't add anything to changes
.
force_change/3
: the always-setter
force_change(changeset, :field, value)
- Always puts the value into
changes
, even if it’s the same as the original. - Useful when you want to force re-validation, trigger change tracking, or update a UI regardless of actual value difference.
Example:
changeset = force_change(changeset, :title, "My Title")
Even if title
hasn't changed, :title
will appear in changes
.
When to Use put_change
- You’re updating user-submitted form data before saving to the DB.
- You want to avoid unnecessary updates.
- You only care about changes that differ from the original.
When to Use force_change
- You want to explicitly mark a field as changed, even if it’s the same as before.
- You’re building a LiveView form and want to reflect the change in the UI.
- You’re triggering behavior that depends on a field being in
changes
(e.g., audit logging, conditionally showing "modified" fields).
LiveView Tip
In Phoenix LiveView, put_change
may not update a form input if the value hasn't changed from the original data — even if the user clicks a button to "reset" or reapply it. Using force_change
ensures the change is tracked and visible in the form.
If this post was enjoyable or useful for you, please share it! If you have comments, questions, or feedback, you can email my personal email. To get new posts, subscribe use the RSS feed.