使用malsup的respond_to ... format.json和jQuery Form Plugin

时间:2022-11-28 14:30:08

I'm having a tad bit of trouble getting the jQuery Form Plugin to work properly with a file-upload field. When I use the plugin to submit the form without a file-upload field, the format.json portion of the respond_to do |format| block is called properly. However, by adding the file-upload field, it only executes the format.html portion which makes my javascript code think that an error has occurred.

我在使用文件上传字段使jQuery Form Plugin正常工作时遇到了一些麻烦。当我使用插件提交没有文件上传字段的表单时,respond_to的format.json部分执行|格式化|块被正确调用。但是,通过添加文件上传字段,它只执行format.html部分,这使得我的javascript代码认为发生了错误。

Has anyone run into this before or know a way to force the plugin to always use json? Alternatively, can I modify the url that the plugin uses to force Rails to render the json?

有没有人遇到这个或知道一种方法来强制插件总是使用json?或者,我可以修改插件用来强制Rails渲染json的url吗?

Thanks very much for any help! Code below:

非常感谢您的帮助!代码如下:

# app/controllers/details_controller.rb
def create
  @detail = Detail.new(params[:detail])

  style = params[:detail_style].to_sym || :thumb
  data = { :id => '5', :url => 'test.rails' }

  respond_to do |format|
    if @detail.save
      flash[:notice] = 'Your image has been saved.'
      data = { :id => @detail.id, :url => @detail.data.url(style) }

      format.html { redirect_to :action => 'index' }
      format.json { render :json => "<textarea>#{data.to_json}</textarea>", :status => :created }
    else
      format.html { render :action => 'new' }
      format.json { render :json => @detail.errors, :status => :unprocessable_entity }
    end
  end
end

/* app/views/sidebar/_details.html.erb (excerpt) */

<% form_for(Detail.new, :html => { :multipart => true } ) do |f| %>
  <%= hidden_field_tag 'detail_style', 'thumb' %>

  <%= f.label :image, "Recent Images" %>
  <%= f.file_field :image%>

  <p> 
    <%= f.submit "Upload" %>
  </p>
<% end %>

<script>
$(document).ready(function() {
  var options = {
    dataType: 'json',

    success: function(json, statusText) {
      console.log("success: " + json);
    },

    error: function(xhr, statusText, errorThrown) {
      console.log("error: " + xhr.responseText);
    }
  };

  $('#new_detail').ajaxForm(options);
});

5 个解决方案

#1


1  

Apparently, setting Accept header is not possible when ajaxSubmit is used and a file is uploaded.

显然,使用ajaxSubmit并上传文件时,无法设置Accept标头。

See malsup's answer in this thread here.

请参阅此帖子中的malsup答案。

He says:

他说:

File uploads don't use ajax, the form plugin only makes it appear that way. A true browser submit takes place when uploading a file.

文件上传不使用ajax,表单插件只会让它显示出来。上传文件时会发生真正的浏览器提交。

#2


7  

Several things are needed to make jQuery Form plugin work for file uploads with a JSON response. In the javascript, the options for .ajaxForm should have:

需要做一些事情才能使jQuery Form插件适用于带有JSON响应的文件上传。在javascript中,.ajaxForm的选项应该具有:

dataType: 'json', // evaluate return as JSON

The browser needs to tell the Rails action to return content as JSON, one way to do this is add a hidden format input field in the file upload form template:

浏览器需要告诉Rails操作将内容作为JSON返回,一种方法是在文件上传表单模板中添加隐藏格式输入字段:

<%= hidden_field_tag 'format', 'json' %>

The Rails action will then run the format.json method inside the respond_to block.

然后,Rails操作将在respond_to块中运行format.json方法。

In the server action

在服务器操作中

  • encapsulate JSON in a tag, .ajaxForm will unwrap the string and eval JSON correctly
  • 将JSON封装在标记中,.ajaxForm将正确地解包字符串和eval JSON
  • set return content type to “text/html”, otherwise some browsers (Firefox) will try to download the return into a file.
  • 将返回内容类型设置为“text / html”,否则某些浏览器(Firefox)会尝试将返回内容下载到文件中。

e.g.

例如

  respond_to do |format|
    format.json {
          render :json => "<textarea>#{data.to_json}</textarea>", :content_type => "text/html"
    }
  }

#3


2  

I did a workaround for this problem. I tested this solution only with Rails 3, but maybe it works also for the 2.3.x

我为这个问题做了一个解决方法。我只用Rails 3测试了这个解决方案,但也许它适用于2.3.x.

The solution is very simple:

解决方案非常简单:

!#javascript

$('form#my_form').live('submit',function(){ 
 $(this).ajaxForm({ dataType: "script", success: processJson})
 return false;
})

//data arrive as a string but we can parse it correctly

function processJson(data, statusText, xhr, $form){
 my_data_parsed = JSON.parse(data); 

  }

!#ruby 
def create
....   
render :js =>  { :status => false,:messages => @myobject.errors.full_messages}.to_json 

end 

#4


1  

Can you examine the post to the server with firebug, and paste the request headers here. We're looking to see that the Accept header is set to json. Also, what version of rails are you using?

您可以使用firebug检查服务器的帖子,并在此处粘贴请求标头。我们希望看到Accept标头设置为json。另外,您使用的是哪种版本的导轨?

#5


1  

I'm still not sure why it doesn't work, but I tried many things and finally found the solution.

我仍然不确定为什么它不起作用,但我尝试了很多东西,最后找到了解决方案。

I tried changing the url by adding .json to the end which forced Rails to render the format.json block, but it confused my browser by making it think I wanted to download a file.

我尝试通过添加.json来强制Rails渲染format.json块来更改url,但它让我认为我想要下载文件使我的浏览器感到困惑。

So, I then tried modifying the url by passing the parameter ?format=json which unfortunately did the exact same thing.

所以,然后我尝试通过传递参数?format = json来修改url,遗憾的是它做了完全相同的事情。

Eventually, I tried changing the format.json to just format.js (Javascript) and adding .js to the url, but still using the same render :json => ... that I had before along with setting the dataType parameter in my jQuery call to json. This appears to work even though it's not the most optimal solution.

最后,我尝试将format.json更改为format.js(Javascript)并将.js添加到url中,但仍然使用相同的渲染:json => ...之前我在设置dataType参数时使用了jQuery调用json。即使它不是最佳解决方案,这似乎也可行。

I hope somebody else finds this useful. I'll post again if I find a proper answer. In the meantime, if anybody else has a proper answer, let me know and I'll accept yours!

我希望别人觉得这很有用。如果我找到合适的答案,我会再次发帖。与此同时,如果其他人有正确的答案,请告诉我,我会接受你的!

#1


1  

Apparently, setting Accept header is not possible when ajaxSubmit is used and a file is uploaded.

显然,使用ajaxSubmit并上传文件时,无法设置Accept标头。

See malsup's answer in this thread here.

请参阅此帖子中的malsup答案。

He says:

他说:

File uploads don't use ajax, the form plugin only makes it appear that way. A true browser submit takes place when uploading a file.

文件上传不使用ajax,表单插件只会让它显示出来。上传文件时会发生真正的浏览器提交。

#2


7  

Several things are needed to make jQuery Form plugin work for file uploads with a JSON response. In the javascript, the options for .ajaxForm should have:

需要做一些事情才能使jQuery Form插件适用于带有JSON响应的文件上传。在javascript中,.ajaxForm的选项应该具有:

dataType: 'json', // evaluate return as JSON

The browser needs to tell the Rails action to return content as JSON, one way to do this is add a hidden format input field in the file upload form template:

浏览器需要告诉Rails操作将内容作为JSON返回,一种方法是在文件上传表单模板中添加隐藏格式输入字段:

<%= hidden_field_tag 'format', 'json' %>

The Rails action will then run the format.json method inside the respond_to block.

然后,Rails操作将在respond_to块中运行format.json方法。

In the server action

在服务器操作中

  • encapsulate JSON in a tag, .ajaxForm will unwrap the string and eval JSON correctly
  • 将JSON封装在标记中,.ajaxForm将正确地解包字符串和eval JSON
  • set return content type to “text/html”, otherwise some browsers (Firefox) will try to download the return into a file.
  • 将返回内容类型设置为“text / html”,否则某些浏览器(Firefox)会尝试将返回内容下载到文件中。

e.g.

例如

  respond_to do |format|
    format.json {
          render :json => "<textarea>#{data.to_json}</textarea>", :content_type => "text/html"
    }
  }

#3


2  

I did a workaround for this problem. I tested this solution only with Rails 3, but maybe it works also for the 2.3.x

我为这个问题做了一个解决方法。我只用Rails 3测试了这个解决方案,但也许它适用于2.3.x.

The solution is very simple:

解决方案非常简单:

!#javascript

$('form#my_form').live('submit',function(){ 
 $(this).ajaxForm({ dataType: "script", success: processJson})
 return false;
})

//data arrive as a string but we can parse it correctly

function processJson(data, statusText, xhr, $form){
 my_data_parsed = JSON.parse(data); 

  }

!#ruby 
def create
....   
render :js =>  { :status => false,:messages => @myobject.errors.full_messages}.to_json 

end 

#4


1  

Can you examine the post to the server with firebug, and paste the request headers here. We're looking to see that the Accept header is set to json. Also, what version of rails are you using?

您可以使用firebug检查服务器的帖子,并在此处粘贴请求标头。我们希望看到Accept标头设置为json。另外,您使用的是哪种版本的导轨?

#5


1  

I'm still not sure why it doesn't work, but I tried many things and finally found the solution.

我仍然不确定为什么它不起作用,但我尝试了很多东西,最后找到了解决方案。

I tried changing the url by adding .json to the end which forced Rails to render the format.json block, but it confused my browser by making it think I wanted to download a file.

我尝试通过添加.json来强制Rails渲染format.json块来更改url,但它让我认为我想要下载文件使我的浏览器感到困惑。

So, I then tried modifying the url by passing the parameter ?format=json which unfortunately did the exact same thing.

所以,然后我尝试通过传递参数?format = json来修改url,遗憾的是它做了完全相同的事情。

Eventually, I tried changing the format.json to just format.js (Javascript) and adding .js to the url, but still using the same render :json => ... that I had before along with setting the dataType parameter in my jQuery call to json. This appears to work even though it's not the most optimal solution.

最后,我尝试将format.json更改为format.js(Javascript)并将.js添加到url中,但仍然使用相同的渲染:json => ...之前我在设置dataType参数时使用了jQuery调用json。即使它不是最佳解决方案,这似乎也可行。

I hope somebody else finds this useful. I'll post again if I find a proper answer. In the meantime, if anybody else has a proper answer, let me know and I'll accept yours!

我希望别人觉得这很有用。如果我找到合适的答案,我会再次发帖。与此同时,如果其他人有正确的答案,请告诉我,我会接受你的!