Live View - 2 submit buttons - identify which one was pressed?

I’m currently re-writing my form to create/edit Log entries with Phoenix Live View. I have an unorthodox UI - it has 2 submit buttons. 1 for “Work” and one for “Break” - offering the user the choice, but allowing the user to submit the form at the same time. So at the time of submitting the form - I need to know which button the user pressed.

In a traditional POST I use the name of the button - in my template I have the following:

<%= submit "Work", name: "work" %>
<%= submit "Break", name: "break" %>

If the user clicks a button, either work or break would exist in the list of params.

In a Live View, I don’t have this technique at my disposal. handle_event does not include the name of the submit button that was pressed.

I tried adding a phx-value-work attribute (which seems like an awesome way to solve this), but that only works with phx-click.

Does anybody have any suggestions?


I’m thinking at this stage that I may be better off creating some client-side javascript to set a hidden field before the form is POSTed. I might have a look at the JS interop mechanism and see what’s possible there…

Does this thread help? It sounds like a similar situation.

It does. Looks like I do need to set a hidden field using javascript before phx-submit event is fired.

Though, I think I might start by adding a phx-click first:

<%= submit "Work", name: "work", "phx-click": :set_work %>
<%= submit "Break", name: "break", "phx-click": :set_break %>

In my code I have something similar to this;

  def handle_event("set_work", _params, socket), do: { :noreply, assign( socket, :work, true) }
  def handle_event("set_break", _params, socket), do: { :noreply, assign( socket, :work, false) }

  def handle_event("save", params, socket) do
     # Do database operation here

I’m assuming this results in 2 round trips (phx-click followed by phx-submit), but the code is easier to read. I might do this for now until I’ve fleshed out my form


If we aren’t passing more information to handle_event and it helps your case, I think we should! It is so common to include two buttons in a form so something like this should be simple to handle.

Would you mind opening an issue in the LiveView repo so we can discuss?

1 Like

No problem!


In case of anyone come across this topic. Here is my solution for this particular issue.

   <! -- We don't need hidden_input here. -->
  <button type="submit" id="foo-btn" phx-hook="HandleSubmitForm" name="foo" phx-hook="SetButtonState">Save</button>
  <button type="submit" id="baz-btn" phx-hook="HandleSubmitForm" name="baz" phx-hook="SetButtonState">Save and Close</button>

Js logic with jquery

// Your phx-hook logic.
// Instead of common way of submitting form, we're handling form submission with ajax.
$(this.el).on('click', '#buttonID', function(evt) {
  let targetButton ="name")
  let form = document.getElementById("yourFormID")
  const formData = new FormData(form)
  formData.append("button", targetButton) # pattern match on this on server side.

    url: "/broadcast", # Route for your controller.
    type: "PUT", # PUT or POST
    data: formData,
    processData: false,
    contentType: false,
    headers: {
      X_CSRF_TOKEN: yourCsrfToken
  .done((resp) => {
    # Do something with resp
  .fail((err) => {
    # Do something with err

Use a controller to handle ajax request.

# And then in your broadcast controller.
  def send(conn, params) do
   data = params # Handling data from the form.
    Phoenix.PubSub.broadcast( # Broadcast updates to LiveView
      {:update_content, %{data: data}}

    send_resp(conn, 200, "ok") # Send some response or err
# Dont forget to subscribe topic in your mounted LiveView
def mounted(_params, _session, socket) do
  Phoenix.PubSub.subscribe(YourApp.PubSub, broadcast_topic)

And finally handle_info/2

  def handle_info({:update_content, %{data: data}}, socket) do
    # Do something with updated data
    {:noreply, socket}

Isn’t this kind of convoluted?

This issue can be solved purely on the client side with javascript, which you’re already doing. Instead of initiating an ajax call, why not simply set a hidden input on the form?

1 Like

My first intuition here would be to use phx-click instead, and pull the form data out of the assigns manually (assuming you’re using live validation).