简体   繁体   中英

Rails/Javascript: Why do I get an error when I submit my form via javascript `submit()`?

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?

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!

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM