User registration form with checkbox will not work on submit

I have an User Registration Form where I added a checkbox for Terms and Privacy Policy. On mount the submit button is disabled (socket = assign(socket, disabled_button: true) ) and it is enabled when the checkbox is checked, in handle_event(“toggle”, params, socket). When I check the checkbox I get an error message (see below).

I moved the checkbox outside the form and I got the same error. The same when I created my own form component with just one button for submit.

Thank you for any help you can provide!

 <.simple_form
        :let={f}
        id="registration_form"
        for={@changeset}
        phx-submit="save"
        phx-change="validate"
        phx-trigger-action={@trigger_submit}
        action={~p"/users/log_in?_action=registered"}
        method="post"
        as={:user}
      >
        <.error :if={@changeset.action == :insert}>
          Oops, something went wrong! Please check the errors below.
        </.error>

        <.input field={{f, :email}} type="email" label="Email" required />
        <.input field={{f, :password}} type="password" label="Password" required />
        <.input field={{f, :first_name}} type="text" label="First Name" required />
        <.input field={{f, :last_name}} type="text" label="Last Name" required />
        <.input field={{f, :phone}} type="text" label="Phone" />

        <div>
          <.input field={{f, :terms_privacy_check}} type="checkbox" phx-click="toggle" />
          I have read and agree privacy policy terms of service.
        </div>

        <:actions>
          <button disabled={@disabled_button} phx-disable-with="Creating account..." class="w-full">
            Create an account
          </button>
        </:actions>
      </.simple_form>
def mount(_params, _session, socket) do
    changeset = Accounts.change_user_registration(%User{})

    socket =
      assign(socket, changeset: changeset, trigger_submit: false)
      |> assign(disabled_button: true)

    {:ok, socket, temporary_assigns: [changeset: nil]}
  end
def handle_event("toggle", params, socket) do
      if(params["value"] == "on") do
        socket = assign(socket, disabled_button: false)
      ...
      {:noreply, socket}
    end

The error message:

[error] GenServer #PID<0.1182.0> terminating
** (ArgumentError) missing :for assign to form
(phoenix_live_view 0.18.11) lib/phoenix_component.ex:1957: Phoenix.Component.“form (overridable 1)”/1
(phoenix_live_view 0.18.11) lib/phoenix_live_view/html_engine.ex:35: Phoenix.LiveView.HTMLEngine.component/3
(streaming 0.1.0) lib/streaming_web/components/core_components.ex:202: anonymous fn/2 in StreamingWeb.CoreComponents.“simple_form (overridable 1)”/1

Welcome!

The missing :for assign likely comes from misunderstanding when to use temporary_assigns. According to the docs on DOM patching & temporary assigns:

By default, all LiveView assigns are stateful, which enables change tracking and stateful interactions. In some cases, it’s useful to mark assigns as temporary, meaning they will be reset to a default value after each update. This allows otherwise large but infrequently updated values to be discarded after the client has been patched.

So by setting the temporary_assigns, the changeset assign gets reset to the default value of nil upon the update that happens when handling the "toggle" event. And because for={@changeset} becomes for=nil, the :for assign doesn’t get rendered resulting in the (ArgumentError) missing :for assign to form you’re seeing.

Thank you for your explanation! Now I understand what the error means, but I am still looking for a solution since the temporary_assigns is from the User Registration generated code.

You could simply remove the temporary_assigns e.g. {:ok, socket}.

Alternatively, assuming this code was generated via mix phx.gen.auth, take a look at how the LiveView deals with form validation via this callback or even the mount callback you shared.

Note what it adds to the socket and then update your custom handle_event callback for toggling to do that as well.

Thank you for your help!