I am trying to bind a checkbox to a property in my assigns. My very basic LiveView 0.16.0 module looks like this:
defmodule CheckboxWeb.Live.PlaygroundLive do
use CheckboxWeb, :live_view
def mount(_, _, socket) do
{:ok, assign(socket, counter: 0, is_selected: true)}
end
def render(assigns) do
~H"""
<input type="checkbox" checked={@is_selected} phx-click="toggle">
"""
end
def handle_event("toggle", _, %{assigns: %{counter: counter}} = socket) do
{:noreply, assign(socket, counter: counter + 1)}
end
end
I would expect the checkbox to stay checked after the server response, however the check box toggles on and off. When I add something like data-counter={@counter} to the input element, it behaves as I expect.
Very new to Elixir, Phoenix, and LiveView and feel like I’m missing something really basic here, but have not had much luck figuring out what it is.
Looks like you do not want to create a form for a changeset, so look at “With limited data” and “Without form data” here: Phoenix.HTML.Form — Phoenix.HTML v3.0.4
When you click the checkbox, the browser toggles it, but since you bound click event handler, after the checkbox is toggled by the browser - liveview processes the event and rerenders your template using your old @is_checked value (which didn’t change).
Let’s assume I have checkbox that can be checked only when the server allows to do it. When user checks such checkbox, browser will check it, server will validate some condition, and if validation was unsuccessful, it will uncheck the checkbox and render an error. When user tries to check the checkbox once again, browser will check it but server won’t uncheck it as nothing will change on the server side (server thinks that the checkbox is uncheked).
To handle this scenario, you’ll need to maintain additional state beyond just the checkbox’s checked status. The key is to track the validation history, which can be done using a counter or similar mechanism. Here’s how it works:
When the user first checks the box, the UI updates optimistically while the server validates
If validation fails, you revert the checkbox and store that a validation attempt occurred
On subsequent attempts, you can use this validation history to determine the final state
This way, the server remains the source of truth, but you have the context needed to handle the UI appropriately. Does it make sense?