What actually triggers a validation in LiveView while doing live validation (without changing the database)?


What actually triggers a validation in LiveView while doing live validation (without changing the database)? I’m struggeling with understanding how ecto changesets work in this regard. During live validation (the kind of validation that is added when using mix phx.gen.live) no changes are made to the database. I’m curious how this actually works, without inserting or updating the database.

Is the last line (Map.put(:action, :validate)) responsible?

changeset =
  |> Models.change_model(model_params)
  |> Map.put(:action, :validate)

(or what does it do if that’s not the case?)

I’m in a situation where I want to trigger validation again, after using Changeset.change/2 on an existing changeset (which contains changes that are relevant and should be kept). Right now I’m creating a new changeset and triggering all validations again, but I suspect I’m doing this wrong. Any insight into understanding how and when valid? and errors is updated, is appreciated. I guess it must be explained somewhere in the docs, but I can’t find it here: Ecto.Changeset — Ecto v3.7.1

Thanks in advance!

1 Like

It happens whenever you call Ecto.Changeset.validate_*. Changesets do not “register validations” they validate right when you call the API. This also means there’s no “rerun validations”. That’s simply not how changesets work. So you actually want to create the changeset fresh whenever you have new changes.

With LV you sometimes get partial changes. In this case I suggest first trying to find a way to not receive partial changes (e.g. integrate with the html form) or pulling out changeset.params and merge that with you new data as the input for a new changeset.

That’s interesting.

I always thought these validations were indeed registered. I think that stems from reading in the docs that validations run before constraints, and hence that there is some kind of ordering done at another point in time.

Creating a new changeset makes sense then. Thanks for the suggestion.

Do you know by any chance what the :action is about? Or point me in the right direction?

Validations run before constraints, because constraints are not run by ecto at all, but by the database. Ecto just converts error responses of the db to internal errors for constraints.

The :action is mostly about communicating intend. E.g. phoenix form error helpers only show errors if :action has a value. So you don’t need to create an errorless changeset as the inital changeset backing a form.