It’s not much to look at, but I have a loop rendering some cards with action buttons. These buttons are set using if/else
in the template so they SHOULD be mutually exclusive, but when I click the “Notify me” button, both buttons get rendered (as pictured). The issue isn’t present on first load and doesn’t show up until I click “Notify me”. I’m using LV 0.16 but it also happened on 0.15.
LiveView template:
<%= for act <- @acts do %>
<div class="container items-center px-5 py-12 text-blueGray-500 lg:px-20">
<div class="p-2 mx-auto my-6 bg-white border rounded-lg">
<div class="flex justify-between p-6 py-2 rounded-lg">
<p class="mb-3 text-base leading-relaxed text-blueGray-500"><%= act.name %></p>
<%= if act.notification do %>
<button id="cancelNotification" class="btn btn-thin btn-danger" phx-click="cancel_notification" phx-value-notification_id={act.notification.id}>
Cancel notification
</button>
<% else %>
<button id="createNotification" class="btn btn-thin btn-primary" phx-click="create_notification" phx-value-act_id={act.id}>
Notify me
</button>
<% end %>
</div>
</div>
</div>
<% end %>
LiveView module:
defmodule MyAppWeb.Festival.ActSelectionLive do
use MyAppWeb, :live_view
alias MyApp.Festivals
alias MyApp.Notifications
@impl true
def mount(_params, %{"festival_id" => festival_id} = session, socket) do
new_socket =
socket
|> assign_defaults(session)
|> load_acts_for_user(festival_id)
{:ok, new_socket}
end
@impl true
def handle_event("create_notification", %{"act_id" => act_id}, socket) do
{:ok, _notification} =
act_id
|> Festivals.get_act!()
|> Notifications.create_notification_for_act_and_user(socket.assigns.current_user)
{:noreply, load_acts_for_user(socket, socket.assigns.festival_id)}
end
def handle_event("cancel_notification", %{"notification_id" => notify_id}, socket) do
{:ok, _notification} =
notify_id
|> Notifications.get_notification!()
|> Notifications.delete_notification()
{:noreply, load_acts_for_user(socket, socket.assigns.festival_id)}
end
defp load_acts_for_user(socket, festival_id) do
user = socket.assigns.current_user
acts = Festivals.list_acts_for_festival_and_user(festival_id, user.id)
assign(socket, festival_id: festival_id, acts: acts)
end
end
LiveHelpers file (the source of assign_defaults
defmodule MyAppWeb.Views.Helpers.LiveHelpers do
import Phoenix.LiveView
alias MyApp.Accounts
@doc """
Fetches current user details from session, if present
"""
def assign_defaults(socket, %{"current_user_id" => user_id}) do
assign_new(socket, :current_user, fn -> Accounts.get_user!(user_id) end)
end
def assign_defaults(socket, _session), do: socket
end