Rails - Advanced Forms project - Form tag helpers not working but raw HTML form works?

Howdy, I know I must be missing something completely fundamental here but I cannot figure out what it is, I’ve been reading around and not come up with any answers as to why my code isn’t working.

So, I’ve set up an Airport model and a Flight model with associations which work properly based on me messing around in the console.

I’m trying to get the beginnings of the form working. I’m trying to get two drop down Select fields, one with a list of all of the departing_airports, and another that once that first field has been submitted back to the controller, re-renders the page so the second drop down contains all the airports where there are flights arriving into from the departing airport.

If I build the form in raw HTML tags it seems to function exactly as I expect it to, however if I try and change it to use form_with instead of an HTML form tag, it doesn’t.

The root route is pointing at ‘flights#index’.

Here’s the code:

schema.db

create_table "airports", force: :cascade do |t|
    t.string "code"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

  create_table "flights", force: :cascade do |t|
    t.integer "start_airport_id"
    t.integer "end_airport_id"
    t.integer "duration"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
  end

models/airport.rb

class Airport < ApplicationRecord
    has_many :departing_flights, foreign_key: :start_airport, class_name: "Flight"
    has_many :arriving_flights, foreign_key: :end_airport, class_name: "Flight"
end

models/flight.rb

class Flight < ApplicationRecord
    belongs_to :start_airport, class_name: "Airport"
    belongs_to :end_airport, class_name: "Airport"
end

controllers/flights_controller.rb

class FlightsController < ApplicationController
    def index
        @selected_start = 1
        if (params[:start_airport_id].present?)
            @selected_start = params[:start_airport_id]
            @departing_flights = Airport.find(params[:start_airport_id]).departing_flights
            @destination_airports_select = @departing_flights.map{ |f| [ f.end_airport.code, f.end_airport.id]}
        end
        if(@destination_airports_select == nil)
            @destination_airports_select = ["-"]
        end
        @start_airports_select = Airport.all.map{ |a| [a.code, a.id]}        
    end
end

Now, if I write my index view with a raw HTML Form tag, the page works exactly as I expect it to, I get a dropdown of all the airports, I click the submit button and the page reloads with the second dropdown correctly populated.

Working - HTML Form Tag index.html.erb

<form action="/" method="get">
    <%= label_tag(:start_airport_id, "Flying from:") %>
    <%= select_tag(:start_airport_id, options_for_select(@start_airports_select, @selected_start)) %>
    <%= submit_tag("Get Destinations") %>
</form>
<br>
Destination Airports:
<br>
<form action="/" method="get">
    <%= select_tag(:end_airport_id, options_for_select(@destination_airports_select)) %>

However, if I try and change that to a Rails form helper the page stops working.

Not working - Form helper index.html.erb

<%= form_with(url: "/", method: "get") do %>
    <%= label_tag(:start_airport_id, "Flying from:") %>
    <%= select_tag(:start_airport_id, options_for_select(@start_airports_select, @selected_start)) %>
    <%= submit_tag("Get Destinations") %>
<% end %>
<br>
Destination Airports:
<br>
<form action="/" method="get">
<%= select_tag(:end_airport_id, options_for_select(@destination_airports_select)) %>

Even looking at the raw HTML in Inspect Element in Chrome I can’t see a significant difference in the output except one just doesn’t submit the form. The server responds from the looks of the log, if I select the second option and press the button the server log spits this out:

Started GET "/?utf8=%E2%9C%93&start_airport_id=2" for ::1 at 2020-05-15 14:46:57 +0100
Processing by FlightsController#index as JS
  Parameters: {"utf8"=>"✓", "start_airport_id"=>"2"}
  Airport Load (0.1ms)  SELECT  "airports".* FROM "airports" WHERE "airports"."id" = ? LIMIT ?  [["id", 2], ["LIMIT", 1]]
  ↳ app/controllers/flights_controller.rb:7
  Flight Load (0.1ms)  SELECT "flights".* FROM "flights" WHERE "flights"."start_airport_id" = ?  [["start_airport_id", 2]]
  ↳ app/controllers/flights_controller.rb:8
  Airport Load (0.1ms)  SELECT "airports".* FROM "airports"
  ↳ app/controllers/flights_controller.rb:13
  Rendering flights/index.html.erb within layouts/application
  Rendered flights/index.html.erb within layouts/application (0.8ms)
Completed 200 OK in 24ms (Views: 19.1ms | ActiveRecord: 0.2ms)

But the page doesn’t change. If I type the parameters into the URL, so if I submit localhost:3000/?start_airport_id=3 the page renders correctly.

Apologies if this is a really basic error, I feel like it has to be but I cannot for the life of me figure out what’s going on.

Thanks in advance for any help anyone can offer!
Alex.

form_with submits the form as an ajax request by default. If you look at your server logs as you submit a form_with you can see Processing by FlightsController#index as JS.

You need to add local: true to the form. `<%= form_with(url: “/”, method: “get”, local: true) do %> to submit the request as html.

Hopefully that should resolve the issue but if you still have issues please let us know.

Thank you much for your reply! Since posting the original message I managed to narrow down that it was the data-remote=“true” html attribute that was the cause of my troubles but I didn’t really get why or how to correct it in the form code so thank you for explaining!