Button inside form reloads the entire view

Hello,
I have a page that consists of several user inputs and buttons.
For real-time validation (as well as updating character count) I am using form, but only phx-change, no phx-submit.

My page structure looks roughly like this:

<div class="max-w-5xl">
  <h1 tag here>
  <form phx-change="change_form">
    <%= if some_condition?() do %>
        <textarea> with some styling
       <button phx-click="event_one">Next 1</button>
    <% else %>
      <textarea> with practically the same styling
      <button phx-click="event_two">Next 2</button>
    <% end %>
  </form>
</div>

Pressing Next 1 button updates the state in such a way that some_condition would be fulfilled, and the second text area and Next 2 button would be displayed.
This works without any issues.

The Next 2 button is exactly the same as the first one, and after pressing it similar handle_event function is called.

The problem is that whatever I do (

  • handle_event does have some logic;
  • handle_event immediately returns {:noreply, socket};
  • Next 2 button does not have phx-click at all
    )
    pressing the button reloads the entire page.
    It does send phx-click event (except when I tried removing it), but then console immediately prints [info] GET /my-endpoint, the socket is reconnected, mount is called and the state of the page is reset.

I noticed one thing: if I remove this second button out of the form, it stops acting out. But no problem ever happens with the first button.

Please advise me on what am I missing here.

This will make the button a plain HTML button, so clicking it will cause the form to “submit” and reload the page.

The usual culprit for this sort of behavior is that the LiveView that receives the event crashes. Is there anything else printed to the server log? Can you post the code of your handle_event?

Further to @al2o3cr comments…

If you have a phx-click attribute on the button, but no matching handle_event it will crash the liveview and reload the page. You will see an error in the logs.

If you have a <button> with no type attribute, it will default to a form submit button if the button is contained within a form. See <button>: The Button element - HTML: HyperText Markup Language | MDN for more info.

Try setting the button types to button explicitly to override the default behaviour (e.g. <button type="button" phx-click="event_two">Next 2</button>.

So, there were no crashes, nor any errors in the console.
It literally sent an event and then reloaded the live view.

handle_event had just one line {:noreply, socket}.

And @mindok was totally right: it was missing type="button". Next 1 button had it.
Thanks a lot!