2010-02-09 15 views
5

Estoy teniendo un pequeño problema para que el jQuery Form Plugin funcione correctamente con un campo de carga de archivos. Cuando uso el complemento para enviar el formulario sin un campo de carga de archivos, se llama correctamente a la parte format.json del bloque respond_to do |format|. Sin embargo, al agregar el campo de carga de archivos, solo ejecuta la parte format.html, lo que hace que mi código de JavaScript piense que se ha producido un error.Usando respond_to ... format.json y jQuery Form Plugin por malsup

¿Alguien se ha encontrado con esto antes o sabe una forma de forzar al plugin a usar siempre json? Alternativamente, ¿puedo modificar la URL que usa el complemento para forzar a Rails a renderizar el json?

Muchas gracias por cualquier ayuda! Código debajo:

# 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); 
}); 

Respuesta

1

Aparentemente, la configuración del encabezado Aceptar no es posible cuando se usa ajaxSubmit y se carga un archivo.

Ver la respuesta de malsup en este hilo here.

Dice: subidas

de archivos no utilizan Ajax, la forma plug-in sólo hace que parezca que manera. Al cargar un archivo, se realiza un verdadero envío de navegador.

+0

Intenté configurar el encabezado Accept, en la devolución de llamada beforeSend, pero esto no tuvo ningún efecto. Cuando miré el código de jQuery.form, el objeto XHR que se pasó a beforeSend tiene una función vacía inicializada en "setRequestHeader". Sin embargo, estoy viendo la versión 2.16 del archivo, quizás haya cambios en las versiones posteriores. – Prashant

1

Puede examinar la publicación en el servidor con firebug, y pegue los encabezados de solicitud aquí. Estamos buscando ver que el encabezado Aceptar esté configurado a json. Además, ¿qué versión de rieles estás usando?

+0

Por desgracia, eso es parte del problema. Parece que el plugin está usando un iframe para enviar el formulario, por lo tanto, no se muestra en Firebug (honestamente, no estoy seguro de que este sea el problema, pero no aparece, y sé que está usando un iframe para ...). Cuando funciona correctamente, verifiqué que el encabezado está configurado en json. Ah, y estoy usando Rails 2.3.5. –

1

Todavía no estoy seguro de por qué no funciona, pero probé muchas cosas y finalmente encontré la solución.

Intenté cambiar la URL agregando .json al final, lo que forzó a Rails a representar el bloque format.json, pero confundió mi navegador al hacer que creyera que quería descargar un archivo.

Entonces, intenté modificar la URL pasando el parámetro ?format=json que, lamentablemente, hizo exactamente lo mismo.

Con el tiempo, he intentado cambiar el format.json sólo format.js (Javascript) y añadiendo .js a la url, pero sigue utilizando el mismo render :json => ... que tenía antes, junto con la configuración del parámetro dataType en mi llamada jQuery para json. Esto parece funcionar a pesar de que no es la solución más óptima.

Espero que alguien más lo encuentre útil. Volveré a publicar si encuentro una respuesta adecuada. Mientras tanto, si alguien más tiene una respuesta adecuada, ¡házmelo saber y aceptaré la tuya!

+0

Funciona perfectamente bien en Firefox, pero produce una advertencia en Safari (5.0.5). –

7

Se necesitan varias cosas para hacer que el complemento jQuery Form funcione para subir archivos con una respuesta JSON. En el Javascript, las opciones para .ajaxForm debe tener:

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

El navegador tiene que decir a los rieles de acción para devolver contenido como JSON, una manera de hacer esto es añadir un campo de entrada de formato oculto en el archivo cargar plantilla de formulario:

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

La acción Rails ejecutará entonces el método format.json dentro del bloque responder_.

En la acción del servidor

  • encapsulado JSON en una etiqueta, .ajaxForm se desenvuelva la cuerda y eval JSON correctamente
  • conjunto de tipos de contenido de retorno a “text/html”, de lo contrario algunos navegadores (Firefox) intentará descargar la devolución en un archivo.

e.g.

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

Hice una solución a este problema. He probado esta solución únicamente con los carriles 3, pero a lo mejor funciona también para la 2.3.x

La solución es muy sencilla:

!#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