In template:
<%= for entry <- @payment_destinations do %>
<tr>
<td>
<.button
type="button"
phx-click="set_default"
phx-value-payment_destination_id={entry.id}
>
Make Default
</.button>
</td>
</tr>
<% end %>
In LiveView - this is called and the update happens just fine. However, LiveView is not updated.
@impl true
def handle_event("set_default", %{"payment_destination_id" => payment_destination_id}, socket) do
Amplify.Context.PaymentDestinations.update_payment_destination(%{
"account_id" => socket.assigns.account_id,
"payment_destination_id" => payment_destination_id
})
account_id = socket.assigns.account_id
socket = put_flash(socket, :info, "Default set")
|> assign(:payment_destinations, get_payment_destinations(account_id))
{:noreply, socket}
end
You will need to share more code as there are several things that could be wrong here and it’s impossible to tell from this code alone.
For instance, when you say “the update happens just fine” do you mean that you can confirm in the database or even with a refresh that it’s updated, or do you just mean that the update_payment_destination
function is called without raising? If it returns an ok/error tuple, this code is doing no error handling so it would just chug along as a no-op.
More poignantly, the template code you shared doesn’t have any conditional logic in it that would indicate that the current payment destination is the default or not. At the very least I would expect something like <.button :if={not entry.is_default} ...>Make Default</.button>
.
So I figured it out by just adding this another variable to the socket:
socket =
put_flash(socket, :info, "Default set")
|> assign(:payment_destinations, get_payment_destinations(account_id))
|> assign(:account, Amplify.AccountsContext.get_account(account_id)) # this one
However, I don’t necessarily understand this. In the loop I do a comparison between account.payment_destination.id
and entry.id
to see which one is the default payment_destination and show a message. Even though account
hadn’t changed, I needed to pass it for the loop to do the right comparison. Do you know why?
This is the comparison code in the loop:
<%= if @account.payment_destination != nil and
@account.payment_destination.id == entry.id do %>
<div class="badge">Default</div>
<% end %>
What was it before? Assuming account.payment_destination
is the default account destination then yes, that makes sense because the account
that I assume is originally assigned in the mount
isn’t automatically updated. Elixir is an immutable language, so there are no references to structs as there are to objects in OO languages. If I say account = get_account(1)
then update_account(account)
without re-assigning it, account
is still going to be the old data. That is if I understand your thinking correctly.
1 Like
Thank you. You’re absolutely right.