jQuery ajax 请求不会触发来自 rails 控制器的 JS 响应?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/6919801/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
jQuery ajax request not triggering JS response from rails controller?
提问by David Tuite
I have a standard controller which is set up to respond to HTML, JS and JSON requests:
我有一个标准控制器,用于响应 HTML、JS 和 JSON 请求:
def picture
@picture = Picture.new params[:picture]
respond_to do |format|
if @picture.save
format.html do
logger.debug "In the HTML responder"
redirect_to @picture
end
format.json { render json: @picture, status: :created, location: @picture }
format.js { render :nothing => true }
else
# you get the idea
end
end
end
Now I'm trying to send a request to that controller with the $.ajax
function (I can't use :remote => true
in this specific situation - I'm trying to make ajax file upload work).
现在我正在尝试使用该$.ajax
功能向该控制器发送请求(我无法:remote => true
在这种特定情况下使用 - 我正在尝试使 ajax 文件上传工作)。
$.ajax({
url: $("form#new_picture").attr("action"),
type: "POST",
data: formdata,
processData: false,
contentType: false
});
The problem is that my request is being treated as a HTML request for some reason. How do I tell rails that I want a JS response?
问题是我的请求由于某种原因被视为 HTML 请求。我如何告诉 rails 我想要一个 JS 响应?
By the way, I'm using jquery_ujs in my project so I have access to the methods it provides if necessary. I'm not really good enough at JS to tweak that to do what I need here.
顺便说一下,我在我的项目中使用了 jquery_ujs,所以我可以在必要时访问它提供的方法。我不太擅长 JS 来调整它来做我在这里需要的东西。
回答by ndemoreau
This solution didn't work for me (rails 3.1 + coffeescript). After searching quite a lot, I found the good way to do it and I wanted to share:
这个解决方案对我不起作用(rails 3.1 + coffeescript)。在搜索了很多之后,我找到了这样做的好方法,我想分享一下:
Just add ".js" to the end of the url. So simple... ;-)
只需在 url 末尾添加“.js”即可。很简单... ;-)
回答by shlensky
Just add dataType: 'script'
只需添加 dataType: 'script'
$.ajax({
url: $("form#new_picture").attr("action"),
type: "POST",
data: formdata,
processData: false,
contentType: false,
dataType: 'script'
});
回答by David Tuite
You have to set the 'accept' header before sending the ajax request so that Rails knows how to respond.
您必须在发送 ajax 请求之前设置 'accept' 标头,以便 Rails 知道如何响应。
$.ajax({
url: $("form#new_picture").attr("action"),
type: "POST",
data: formdata,
processData: false,
contentType: false,
beforeSend: function(xhr, settings) {
xhr.setRequestHeader('accept', '*/*;q=0.5, ' + settings.accepts.script);
}
});
回答by overallduka
Add dataType: 'script'
and in data of form add the parameter format: 'js'
like this:
添加dataType: 'script'
并在表单数据中添加如下参数format: 'js'
:
$.ajax({
url: '/manager/consumers/url',
type: 'GET',
dataType: 'script',
data: {
authenticity_token: '<%= form_authenticity_token %>',
param_1: '1',
param_2: '2',
format: 'js'
}
});
also add in the controller to not render layout:
还要在控制器中添加不渲染布局:
respond_to do |format|
format.xls
format.js { render :layout => false }
end
回答by user3375663
You can check whether it is a xhr request and render the format you prefer. For Example;
您可以检查它是否是 xhr 请求并呈现您喜欢的格式。例如;
if request.xhr?
render :json => {
:some_data => 'bla'
}
end
回答by 92tonywills
Although possibly not directly answering the question, I came across this with a similar problem and others may find this helpful. Especially if you use haml.
虽然可能没有直接回答这个问题,但我遇到了类似的问题,其他人可能会觉得这很有帮助。特别是如果你使用haml。
After many attempts (including appending .js to the url) the only thing that worked for me was disabling the layout renderer when returning a script response.
经过多次尝试(包括将 .js 附加到 url)后,唯一对我有用的是在返回脚本响应时禁用布局渲染器。
respond_to do |format|
format.html
format.js { render layout: false }
end
My problem was that the AJAX response was a full html page generated by the rails layout template mechanism. This meant my javascript in my thing.js.erb
wasn't executing. Disabling the layout meant only the javascript was returned (you can find the return in you browsers network tab of the developer pane) which allowed it to be executed.
我的问题是 AJAX 响应是由 rails 布局模板机制生成的完整 html 页面。这意味着我的 javascriptthing.js.erb
没有执行。禁用布局意味着只返回 javascript(您可以在开发人员窗格的浏览器网络选项卡中找到返回),这允许它被执行。
I'm using haml as my default renderer and I believe that is why I required explicitly disabling the layout in js renders (I had assumed it would be automatic).
我使用 haml 作为我的默认渲染器,我相信这就是为什么我需要明确禁用 js 渲染中的布局(我认为它会是自动的)。
So if nothing else has worked and you use haml, try this.
因此,如果没有其他任何效果并且您使用 haml,请尝试此操作。
回答by Donato
Let me explain what is going on here.
让我解释一下这里发生了什么。
I often get the Accept header and Content-type Header that a client sends to the server confused in HTTP. The Accept header is used to tell the server what content types (application/json, application/javascript, application/octet-stream, audio/mpeg, image/png, multipart/alternative, text/plain, text/html, text/csv, video/mpeg, etc) they'll accept. The server sends back a response, which includes the Content-Type header notifying the client of the actual Content Type of the content.
我经常在 HTTP 中混淆客户端发送到服务器的 Accept 标头和 Content-type 标头。Accept 标头用于告诉服务器什么内容类型(application/json、application/javascript、application/octet-stream、audio/mpeg、image/png、multipart/alternative、text/plain、text/html、text/csv 、视频/mpeg 等)他们会接受。服务器发回一个响应,其中包括 Content-Type 标头,通知客户端内容的实际内容类型。
HTTP requests can also specify Content-Type, because in form data, there could be all types of data, and the Content-Type header can notify the server what the data actually is (e.g. multipart/form-data). The different media types like multipart/form-data are known as MIME.
HTTP 请求也可以指定 Content-Type,因为在表单数据中,可能有所有类型的数据,而 Content-Type 头可以通知服务器数据实际上是什么(例如 multipart/form-data)。不同的媒体类型如 multipart/form-data 被称为 MIME。
Now jQuery.ajax() has another of parameters you can pass it related to this topic: accepts, contentType, dataType.
现在 jQuery.ajax() 有另一个你可以传递给它的与这个主题相关的参数:accepts、contentType、dataType。
The contentType attribute is clear if you understand the Content-Type HTTP header. It tells the server what the data actually is. The default in jQuery is "application/x-www-form-urlencoded; charset=UTF-8", which is fine for most cases.
如果您了解 Content-Type HTTP 标头,则 contentType 属性很清楚。它告诉服务器数据实际上是什么。jQuery 中的默认值是“application/x-www-form-urlencoded; charset=UTF-8”,这在大多数情况下都可以。
Remember that the Accept header tells the server what Content-Type it will accept. But when you read the jQuery documentation for dataType, it sounds quite similar: "The type of data that you're expecting back from the server." So what is the difference?
请记住,Accept 标头告诉服务器它将接受什么 Content-Type。但是当您阅读有关 dataType 的 jQuery 文档时,它听起来非常相似:“您期望从服务器返回的数据类型。” 那么区别是什么呢?
The accepts attribute allows you to change the Accept header in the request. But by changing the dataType it will change the Accept header too, so there is really no need to change the accept attribute; the dataType will change the Accept header. The benefit of dataType is ti allows you to pre-process the response before being available to the succes handler.
accepts 属性允许您更改请求中的 Accept 标头。但是通过改变 dataType 也会改变 Accept 头,所以真的没有必要改变 accept 属性;dataType 将更改 Accept 标头。dataType 的好处是 ti 允许您在可用于成功处理程序之前预处理响应。
In effect, we need to tell Rails what we will accept as a response header, so we modify the dataType. In Rails the symbols :js and :json, for example, correspond to a HTTP Mime Type:
实际上,我们需要告诉 Rails 我们将接受什么作为响应头,因此我们修改了 dataType。例如,在 Rails 中,符号 :js 和 :json 对应于 HTTP Mime 类型:
Mime::Type.register "text/javascript", :js, %w( application/javascript application/x-javascript )
Mime::Type.register "application/json", :json, %w( text/x-json application/jsonrequest )
Thus, if we want to trigger the :js option in the respond_to block, then we need to specify the dataType in jQuery as script. And as one of the answers illustrates, you do it like this:
因此,如果我们想触发 respond_to 块中的 :js 选项,那么我们需要在 jQuery 中将 dataType 指定为脚本。正如其中一个答案所说明的那样,您可以这样做:
$.ajax({
url: "users/populate_user,
type: "POST",
data: formdata,
dataType: 'script'
});
Now look how beautiful the Request Header looks:
现在看看 Request Header 看起来有多漂亮:
Notice how specifying the dataType as script changed the Accept header to application/javascript. Also notice that the contentType is "application/x-www-form-urlencoded; charset=UTF-8". Remember I said this is the default Content-Type jQuery will use if none is specified? Well another answer provided in this SO page specified this option as well:
请注意如何将 dataType 指定为脚本将 Accept 标头更改为 application/javascript。还要注意 contentType 是“application/x-www-form-urlencoded; charset=UTF-8”。还记得我说过如果没有指定,这是 jQuery 将使用的默认 Content-Type 吗?这个 SO 页面中提供的另一个答案也指定了这个选项:
contentType: false
According to the jQuery documentation:
根据 jQuery 文档:
As of jQuery 1.6 you can pass false to tell jQuery to not set any content type header.
从 jQuery 1.6 开始,您可以传递 false 来告诉 jQuery 不要设置任何内容类型标头。
One last point. In your Rails controller, you do not need to specify the :js flag if this controller action is only ever going to be responding to :js. You can simply omit the respond_to from the controller:
最后一点。在您的 Rails 控制器中,如果此控制器操作只会响应 :js,则您不需要指定 :js 标志。您可以简单地从控制器中省略 respond_to :
def populate_user
@user = User.from_names(params[:name][:value]).first
end
And then add a users/populate_user.js.erb file. Also make sure your route is set up for a post request:
然后添加一个 users/populate_user.js.erb 文件。还要确保为发布请求设置了路由:
post 'users/populate_user', to: 'users#populate_user'
When copying and pasting answers from SO, it is also important to understand exactly what you are using in your project.
从 SO 复制和粘贴答案时,准确了解您在项目中使用的内容也很重要。
回答by shweta
Set contentType
as "text/javascript"
设置contentType
为"text/javascript"
$.ajax({
url: $("form#new_picture").attr("action"),
type: "POST",
data: formdata,
processData: false,
contentType: "text/javascript"
});