Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
968 views
in Technique[技术] by (71.8m points)

ruby - Controller can not detect ajax requests

I am using simple_form gem and generating the form I am specifying the remote:true option like this:

<%= simple_form_for @webinar, validate: true, remote:true do |f| %>

So, the output html for the form is the following fragment:

<form accept-charset="UTF-8" action="/webinars" class="simple_form new_webinar" data-remote="true" data-validate="true" enctype="multipart/form-data" id="new_webinar" method="post" novalidate="novalidate"> ... </form>

As I checked, using the standard form_for helper is adding the data-remote='true' to the form when remote:true options is used. And as you can see from the generated html, when I am using the simple_form gem there is such attribute, too.

So, in my controller I have:

def create
  @webinar = Webinar.new(params[:webinar])

  respond_to do |format|
    if @webinar.save
      format.html { redirect_to @webinar, notice: 'Webinar was successfully created.' }
      format.js
      format.json { render json: @webinar, status: :created, location: @webinar }
    else
      format.html { render action: "new" }
      format.json { render json: @webinar.errors, status: :unprocessable_entity }
    end
  end
end

But, always the format.html is used. What i am doing wrong?

EDIT:

I have used logger.debug request.format to check what is the actual format ask for and in the log file it was:

text/html

So, the issue must be in the simple_form generated form - what can be wrong there when we have "data-remote=true"?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

You're confusing format.json|format.html with remote: true. Both are different. The presence of remote: true does not imply format.json.

format.json does not indicate that the URL was invoked via javascript. It only means that the client expects JSON output. i.e. it does not indicate where input came from, it indicates what output is required.

The general use of remote:true is, instead of reloading the page, you submit the form as an Ajax request and then show the response in a JQuery popup or something. But if you want to display the response as a JQuery popup - you need HTML output, not JSON output right?

Some people use remote: true to load HTML content in a popup. Your use case is to do remote: true but you're expecting JSON formatted data. Rails cannot make these decisions for you. It by default sends the request to /webinars and expects that you will handle the HTML response. If you really want JSON response - then customize the URL to which the Ajax request is posted:

simple_form_for @webinar, url: webinar_path(format: :json), .....

If you do the above, now the webinar controller will be called with JSON format.

Overall:

  • remote:true can be used with both format.html and format.json
  • The majority use case in a Rails application is to handle remote: true as a controller request as usual, render a partial HTML template (i.e. the response content alone without the overall page layout/navigation/etc) and send it back as HTML to be displayed in a popup
  • Most people just blanket-handle remote callbacks and display a JQuery popup. So they don't need to write individual code for each remote forms
  • So by default, Rails calls format.html for remote requests
  • If you specifically want format.json, and if you really want to handle the JSON manually on the client, change the URL accordingly. But this is not the majority use case
  • Making an Ajax request does not mean the content-type is JSON. It is a HTML request made using Javascript. e.g. In jquery $.ajax method, check these two options: accept and dataType. If you really want to send Accepts: application/json header, then you have to manually specify that when making the Ajax request (or you need to end the url with .json if its a Rails app).
  • So even if you make a normal Ajax request to /webinars, like $.ajax('/webinars', ...) - it won't go to format.json ! It will still only go to format.html. If you really want a JSON format, then you must say $.ajax('/webinars', { accepts: 'application/json' }), or you must say $.ajax('/webinars.json')

Edit: Minor clarification


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...