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.
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?
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);
});
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:
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:
<%= hidden_field_tag 'format', 'json' %>
The Rails action will then run the format.json method inside the respond_to block.
In the server action
e.g.
respond_to do |format|
format.json {
render :json => "<textarea>#{data.to_json}</textarea>", :content_type => "text/html"
}
}
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
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
Apparently, setting Accept header is not possible when ajaxSubmit is used and a file is uploaded.
See malsup's answer in this thread here.
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.
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?
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With