1

I have a form in my pug template that works and gets submitted normally using my Phoenix controller's submit function. I don't want to reload or redirect the page, so I figured I should use an AJAX request to submit the form.

This is the form:

=form_for @invoice_changeset, adaptive_invoice_path(@conn, :update, @adaptive, @invoice), [as: :invoice, method: :put, id: 'add-invoice-remarks-form'], fn f ->
  .form-group
    .label Remarks
    = textarea f, :remarks, id: "remarks-area", role: "add-invoice-remarks", class: "textarea", placeholder: "Add Notes here (enter to submit)"
  .form-group
    = submit "Submit", class: "btn btn-primary btn-block"

This is the function in my controller that handles the submission of the form. It works normally, but refreshes the page.

def update(%Plug.Conn{assigns: %{adaptive: adaptive}} = conn, %{
      "id" => id,
      "invoice" => invoice_params
    }) do
  {:ok, invoice} = Billing.find_invoice(%{"id" => id})

  case Billing.update_invoice(invoice, invoice_remarks) do
    {:ok, invoice} ->
      conn
      |> put_flash(:info, "Invoice update successful!")
      |> redirect(to: adaptive_invoice_path(conn, :show, adaptive, invoice))

    {:error, _changeset} ->
      conn
      |> put_flash(:error, "Something went wrong while adding remarks!")
      |> redirect(to: adaptive_invoice_path(conn, :show, adaptive, invoice))
  end
end

I tried to intercept the form, and submit it with AJAX and onmount, but I receive a Phoenix.Router.NoRouteError upon clicking the submit button even though I have the correct route.

import { post } from '../../api'

onmount('[role="add-invoice-remarks"]', function () {
  const $form = $('#add-invoice-remarks-form')
  $form.on('submit', e => {
    e.preventDefault()

    const action = $form.attr('action')

    const invoiceParams = {
      remarks: $form.find('#remarks-area').val()
    }

    post(
      action,
      {
        invoice: invoiceParams
      },
      _ => {
        show_flash(success_content())
      },
      response => {
        show_flash(fail_content(response))
      }
    )
  })
})

Is there something I missed?

6
  • Please post the error message. Commented Jul 2, 2018 at 4:33
  • @mudasobwa [debug] ** (Phoenix.Router.NoRouteError) no route found for POST /adaptives/6/invoices/3 (Enterprise.Router)
    – Bargain23
    Commented Jul 2, 2018 at 4:45
  • Let me guess: your pipeline accepts html only plug :accepts, ["html"] and you do not have a pipeline that handles json, right? Commented Jul 2, 2018 at 4:47
  • @mudasobwa Okay, I added that in my pipeline, and I still get the same error. If I get rid of the javascript part altogether, I don't get any errors and the controller works as intended, so it can't be the server-side that's causing the problem. However, I still need to prevent the page from refreshing.
    – Bargain23
    Commented Jul 2, 2018 at 5:21
  • Of course it’s the server part. You should explicitly handle this route when the frontend sends JSON and respond with a JSON back. Commented Jul 2, 2018 at 5:24

1 Answer 1

2

You're sending a POST request to a route that's expecting a PUT request.

You need a _method="put" parameter in your in addition to your invoice params.

Something like:

{
  invoice: invoiceParams,
  _method: "put"
}

Not the answer you're looking for? Browse other questions tagged or ask your own question.