Wojciech
I have trouble with simple data update using forms
"I have recently generated authorization using phx.gen and attempted to add an additional field to the table. Subsequently, I implemented a method to update this new field. Then I updated the registration form and added a new form to the settings page. Currently, all functionalities are working as expected, except for the part that allows updating the name.
When i submit form “name_form” i don’t get any errors, but when i look up the database data doesn’t seem to change, i tried using IO.inspect() (probably) everywhere and everything still seems fine.
Form:
<div>
<.simple_form
for={@name_form}
id="name_form"
phx-submit="update_name"
phx-change="validate_name"
>
<.input field={@name_form[:name]} type="text" label="Username" autocomplete="off" required />
<:actions>
<.button phx-disable-with="Changing...">Change username</.button>
</:actions>
</.simple_form>
</div>
I have two event handlers, one for validation and the other for updating:
def handle_event("validate_name", %{"user" => user_params}, socket) do
name_form =
socket.assigns.current_user
|> Accounts.change_user_name(user_params)
|> Map.put(:action, :validate)
|> to_form()
{:noreply, assign(socket, name_form: name_form)}
end
def handle_event("update_name", %{"user" => user_params}, socket) do
user = socket.assigns.current_user
case Accounts.apply_user_name(user, user_params, [validate_name: true]) do
{:ok, _changeset} ->
{:noreply, socket}
{:error, changeset} ->
{:noreply, assign(socket, :form, to_form(changeset))}
end
end
Accounts module, change_user_name returns an %Ecto.Changeset{} for changing the user name:
def change_user_name(user, attrs \\ %{}, opts \\ []) do
User.name_changeset(user, attrs, opts)
end
def apply_user_name(user, attrs, opts \\ []) do
user
|> User.name_changeset(attrs, opts)
|> Ecto.Changeset.apply_action(:update)
end
User module contains validate_name changeset which validates name and checks if name in unique:
def validate_name(changeset, opts) do
changeset
|> validate_required([:name])
|> validate_length(:name, min: 2, max: 36, message: "username must be between 2 and 36 characters")
|> validate_format(:name, ~r/^[^\s]*$/, message: "cannot have a space at the end")
|> maybe_validate_unique_name(opts)
end
def name_changeset(user, attrs \\ %{}, opts \\ []) do
user
|> cast(attrs, [:name])
|> validate_name(opts)
|> case do
%{changes: %{name: _}} = changeset -> changeset
%{} = changeset -> add_error(changeset, :name, "did not change")
end
end
defp maybe_validate_unique_name(changeset, opts) do
if Keyword.get(opts, :validate_name, true) do
changeset
|> unsafe_validate_unique(:name, Elixirlore.Repo)
|> unique_constraint(:name)
else
changeset
end
end
I’d be very grateful for at least some indication where error may be located, thanks in advance.
Marked As Solved
codeanpeace
Welcome!
Hmm, I don’t see any calls to Ecto.Repo that would actually interact with the database e.g. Repo.update/2 to persist the changeset.
And to clarify, Ecto.Changeset.apply_action(changeset, :update) attempts to add the :update action to the changeset – it does not attempt to update the database itself.
Popular in Questions
Other popular topics
Categories:
Sub Categories:
Forums
Popular Tags
- #ecto
- #liveview
- #troubleshooting
- #learning-elixir
- #deployment
- #library
- #erlang
- #testing
- #genserver
- #mix
- #absinthe
- #remote-other
- #otp
- #plug
- #how-to-question
- #macros
- #postgres
- #channels
- #elixirconf
- #exunit
- #discussion
- #javascript
- #code-sync
- #podcasts
- #onsite
- #dialyzer
- #docker
- #authentication
- #umbrella
- #full-time-contract
- #podcasts-by-brainlid
- #ecto-query
- #elixir-ls
- #phoenix_html
- #iex
- #blog-post
- #graphql
- #genstage
- #ai
- #websockets
- #supervisor
- #advent-of-code
- #elixirconf-us
- #distillery
- #processes
- #forms
- #api
- #metaprogramming
- #security
- #performance









