4

I have a search form in a view.

  <%= form_with url: issues_path, class: 'filter-box' do %>
    <%= text_field_tag(:filter_by, '', id: 'filter-text-field') %>
  <% end %>

When the form is submitted, the following action is run:

class IssuesController < ApplicationController
  ...

  def create
    @labels = Label.by_search_term(params[:filter_by])
    respond_to do |format|
      format.js
    end
  end
end

All works well.

However, I want the action to be triggered with every keystroke. To that end, I have added the following javascript.

  <script>
    document.getElementById('filter-text-field').addEventListener('keyup', function(){
      document.querySelector('.filter-box').submit()
    })
  </script>

But when the form is submitted on key up it breaks and I get an error: ActionController::UnknownFormat in IssuesController#create.

Looking at the params, I don't see anything notable.

# Submitted by pressing return
# => <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"TJRajeBbEK8+D0Ly5/lbI/SVx8srhG/YS2W1l+Zc+f+TYmsbfehXnsluxOovblCrWBLJy0exhyzhsY+qPhBDOQ==", "filter_by"=>"d", "controller"=>"issues", "action"=>"create"} permitted: false>

# Submitted on keyup
# => <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"7NBwqCuJpbFGvxWgq6qqdB1hF0yptca0N446G4nQ620zJkE+tjrigLHek7hjPaH8seYZTMWALkCdWgAmUZxRqw==", "filter_by"=>"d", "controller"=>"issues", "action"=>"create"} permitted: false>

What is the difference between submitting the form by pressing enter and submitting the form via javascript? What do I need to do to ensure it works correctly?

user3574603
  • 3,364
  • 3
  • 24
  • 59
  • Check this question https://stackoverflow.com/questions/22943892/actioncontrollerunknownformat it seems like when the format is being submitted the proper format is being sent, but when you do the `keyup` submission you are not sending any format or it's missing so the controller does not know how to render the response. – Danilo Cabello Feb 11 '19 at 14:09

1 Answers1

3

Rails' form_with helper sets the form to be remote: true by default. So, when you submit the form, Rails' UJS steps in the middle and creates an ajax request. When you use the submit() method on the form, it does not allow Rails to handle the ajax request properly because it does not trigger the events Rails is expecting.

You can use Rails' javascript object helper methods to trigger the submission instead of the javascript's submit() method. Something like:

document.getElementById('filter-text-field').addEventListener('keyup', function(){
  Rails.fire(this.form, 'submit')
})

This will trigger the 'submit' event instead of submitting the form, so now all rails' callback will handle rails' attributes like remote: true, disable_with: ..., confirm: ..., etc.

EDIT: addign references: https://github.com/rails/rails/tree/master/actionview/app/assets/javascripts/rails-ujs

start.coffee sets the events callbacks and utils/events.coffee defines the fire function

EDIT2: This is the part where Rails adds all the callbacks for the form's submit event https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts/rails-ujs/start.coffee#L55-L62

This is the function to fire events using Rails' helper class https://github.com/rails/rails/blob/master/actionview/app/assets/javascripts/rails-ujs/utils/event.coffee#L34

I'm not sure if there's a DOC for this, I've learned this reading the code on my own, I'm not sure where to point you other than the source, sorry!

arieljuod
  • 15,460
  • 2
  • 25
  • 36
  • Thanks. I'm having trouble finding a reference to this in the documentation. I'd be thankful if anyone could point me towards the relevant pages. – user3574603 Feb 11 '19 at 15:14
  • 1
    @user3574603 I've added the links to the actual source, I really don't know if there's an official doc for this – arieljuod Feb 11 '19 at 16:52