turbolinks / turbolinks-ios

Native iOS adapter for building hybrid apps with Turbolinks 5
MIT License
881 stars 92 forks source link

Best practices for GET remote form submit #132

Open brandonhilkert opened 6 years ago

brandonhilkert commented 6 years ago

We have a search form that uses GET to filter on the collection:

        <%= form_tag nil, method: :get, remote: true do |form| %>

The response itself is a normal Rails action returning the entire template. It looks like I incorrectly assumed Turbolinks would handle this similar to a link.

What's the best practice around modifying search-style forms?

jeffmcfadden commented 6 years ago

In our app we just build and use an XMLHTTPRequest for the search, via GET, and then replace a section in the page with the relevant result (for us that's a partial, rendered by the controller with a nil layout).

jakobdamjensen commented 6 years ago

We listen to the ajax:create event created by rails-ujs remote form submit event like so

$(document).observe("ajax:create", function (event, res, other, third) {
      var target = event.target
      var targetDataset = target.dataset
      var url = event.memo.request.url

      if (targetDataset && targetDataset.remote) {
        if (target.method === "get") {
          event.stop()
          Turbolinks.visit(url)
        }
      }
    })

This was implemented in a very old rails application using prototype. So you need to adapt this to jQuery/vanillajs if you do not use prototype. This is all done on the server and only when the native apps request the pages.

henrik commented 5 years ago

We do this (CoffeeScript and jQuery), adding a .js-turbolinks-get-form class to each form:

 # Makes GET forms work with Turbolinks, by simply visiting the URL they would submit to.

 $(document).on "submit", ".js-turbolinks-get-form", (e) ->
   url = $(this).attr("action") + "?" + $(this).serialize()
   Turbolinks.visit(url)

   e.preventDefault()
brandonhilkert commented 5 years ago

FWIW, we added the following (very similar to @henrik's solution, just doesn't require additional class on form):

$(document).on "submit", "form[method=get][data-remote=true]", (e) ->
  e.preventDefault()
  url = this.action + '?' + $(this).serialize()
  Turbolinks.visit url
  false