2009-09-28 19 views
29

¿Existe un complemento jQuery que pueda serializar un formulario y luego restaurar/completar el formulario dado el valor serializado? Sé que el complemento de formulario puede serializar como una cadena de consulta, pero no he encontrado nada que restablezca el formulario de la cadena de consulta.jQuery plugin para serializar un formulario y también restaurar/llenar el formulario?

Lo que me gustaría hacer es serializar los valores del formulario, almacenar como una cookie cada vez que el formulario cambie, y luego restaurar el formulario de la cookie (si existe) cuando la página se carga por primera vez.

He encontrado piezas de este rompecabezas (plugin de formulario, complemento de cookies, varios complementos de autoguardado que no se restauran), pero antes de improvisar algo de varias partes, quería asegurarme de que no hubiera un buena solución enlatada esperándome por ahí.

Gracias!

Jim

Respuesta

38

Aquí hay un poco algo que rodó Basado en el trabajo de los demás, específicamente serializeAnything:

/* jQuery.values: get or set all of the name/value pairs from child input controls 
* @argument data {array} If included, will populate all child controls. 
* @returns element if data was provided, or array of values if not 
*/ 

$.fn.values = function(data) { 
    var els = $(this).find(':input').get(); 

    if(typeof data != 'object') { 
     // return all data 
     data = {}; 

     $.each(els, function() { 
      if (this.name && !this.disabled && (this.checked 
          || /select|textarea/i.test(this.nodeName) 
          || /text|hidden|password/i.test(this.type))) { 
       data[this.name] = $(this).val(); 
      } 
     }); 
     return data; 
    } else { 
     $.each(els, function() { 
      if (this.name && data[this.name]) { 
       if(this.type == 'checkbox' || this.type == 'radio') { 
        $(this).attr("checked", (data[this.name] == $(this).val())); 
       } else { 
        $(this).val(data[this.name]); 
       } 
      } 
     }); 
     return $(this); 
    } 
}; 
+0

¡Guau! Se guardará esto para uso futuro. –

+0

¡Muy bueno! Solo tendré que agregar un paso de/a JSON para poder almacenar el estado serializado como una cookie. ¡Gracias! –

+0

Alguien tiene que hacer un complemento oficial de esto :) –

3

Muchas gracias a Barnabas Kendall por su respuesta, muy útil.

Sin embargo, encontré 1 error en la restauración de botones de radio, donde en lugar de seleccionar el correcto, simplemente copió el valor guardado en todos los botones del grupo.

Afortunadamente es fácil de arreglar. Basta con sustituir

if(this.type == 'checkbox') { 

Con

if(this.type == 'checkbox' || this.type == 'radio') { 

y se actualizará correctamente los botones de radio

6

Gracias a Bernabé Kendall para la función inicial y Eggert Jóhannesson para fijar botón de radio!

He encontrado un problema con las casillas de verificación; si no se marcan, no se colocarán en la matriz, hasta ahora todo va bien. Pero como el estado de las casillas de verificación no está almacenado cuando no están marcadas, no pude restaurar este estado si el usuario las había revisado durante la edición del formulario.

Así que amplió la funcionalidad de restauración de desactivar todas las casillas de verificación que no están en la matriz de datos, esto asegurará el estado de casillas de verificación se restaura correctamente sin importar lo que fue cambiado en la forma antes de ejecutar la restauración:

if (this.name && data[this.name]) { 
    if(this.type == "checkbox" || this.type == "radio") { 
     $(this).prop("checked", (data[this.name] == $(this).val())); 
    } else { 
     $(this).val(data[this.name]); 
    } 
} else if (this.type == "checkbox") { 
    $(this).prop("checked", false); 
} 

completar la función:

$.fn.values = function(data) { 
    var inps = $(this).find(":input").get(); 

    if(typeof data != "object") { 
     // return all data 
     data = {}; 

     $.each(inps, function() { 
      if (this.name && (this.checked 
         || /select|textarea/i.test(this.nodeName) 
         || /text|hidden|password/i.test(this.type))) { 
       data[this.name] = $(this).val(); 
      } 
     }); 
     return data; 
    } else { 
     $.each(inps, function() { 
      if (this.name && data[this.name]) { 
       if(this.type == "checkbox" || this.type == "radio") { 
        $(this).prop("checked", (data[this.name] == $(this).val())); 
       } else { 
        $(this).val(data[this.name]); 
       } 
      } else if (this.type == "checkbox") { 
       $(this).prop("checked", false); 
      } 
     }); 
     return $(this); 
    } 
}; 
12

he ampliado sobre la respuesta Bernabé con lo siguiente:

  1. Admite múltiples entradas con el mismo nombre (las casillas de verificación suelen hacer esto).
  2. selectores caché cuando sea posible, eliminar el uso innecesario de $

    /* jQuery.values: get or set all of the name/value pairs from child input controls 
        * @argument data {array} If included, will populate all child controls. 
        * @returns element if data was provided, or array of values if not 
        */ 
    
        $.fn.values = function(data) { 
         var els = this.find(':input').get(); 
    
         if(arguments.length === 0) { 
          // return all data 
          data = {}; 
    
          $.each(els, function() { 
           if (this.name && !this.disabled && (this.checked 
               || /select|textarea/i.test(this.nodeName) 
               || /text|hidden|password/i.test(this.type))) { 
            if(data[this.name] == undefined){ 
             data[this.name] = []; 
            } 
            data[this.name].push($(this).val()); 
           } 
          }); 
          return data; 
         } else { 
          $.each(els, function() { 
           if (this.name && data[this.name]) { 
            var names = data[this.name]; 
            var $this = $(this); 
            if(Object.prototype.toString.call(names) !== '[object Array]'){ 
             names = [names]; //backwards compat to old version of this code 
            } 
            if(this.type == 'checkbox' || this.type == 'radio') { 
             var val = $this.val(); 
             var found = false; 
             for(var i = 0; i < names.length; i++){ 
              if(names[i] == val){ 
               found = true; 
               break; 
              } 
             } 
             $this.attr("checked", found); 
            } else { 
             $this.val(names[0]); 
            } 
           } 
          }); 
          return this; 
         } 
        }; 
    
+0

¿Podría hacer un jsfiddle o similar para mostrar en uso? Hice una demostración simple aquí http://codepen.io/jasondavis/pen/jsmya pero no tengo las casillas de verificación/de radio funcionando correctamente – JasonDavis

+1

la razón por la que no puedes hacer que funcione es porque lo estás haciendo mal :) check/radio los botones tienen valores y eso es lo que guarda/establece: http://codepen.io/anon/pen/xKizw – mkoryak

+0

Debería estar usando '.prop' en lugar de' .attr' Ver: http://stackoverflow.com/ questions/5874652/prop-vs-attr – chodorowicz

0

Para serializar en una cadena: var s = $('form').first().serialize();

Para restauración basan en esa cadena: $('form').first().deserialize(s);

Por supuesto, necesitará un plugin desrserialize como el que yo originally posted here.

$.fn.deserialize = function (serializedString) 
{ 
    var $form = $(this); 
    $form[0].reset(); 
    serializedString = serializedString.replace(/\+/g, '%20'); 
    var formFieldArray = serializedString.split("&"); 

    // Loop over all name-value pairs 
    $.each(formFieldArray, function(i, pair){ 
     var nameValue = pair.split("="); 
     var name = decodeURIComponent(nameValue[0]); 
     var value = decodeURIComponent(nameValue[1]); 
     // Find one or more fields 
     var $field = $form.find('[name=' + name + ']'); 

     // Checkboxes and Radio types need to be handled differently 
     if ($field[0].type == "radio" || $field[0].type == "checkbox") 
     { 
      var $fieldWithValue = $field.filter('[value="' + value + '"]'); 
      var isFound = ($fieldWithValue.length > 0); 
      // Special case if the value is not defined; value will be "on" 
      if (!isFound && value == "on") { 
       $field.first().prop("checked", true); 
      } else { 
       $fieldWithValue.prop("checked", isFound); 
      } 
     } else { // input, textarea 
      $field.val(value); 
     } 
    }); 
    return this; 
} 

Más información: https://stackoverflow.com/a/24441276/1766230

Aquí hay una jsFiddle que te permite jugar con los valores de ajuste, la limpieza, la restauración, y "deserializar": http://jsfiddle.net/luken/4VVs3/

+2

Se produce un error cuando hay un campo Seleccionar con el atributo "múltiple". – tamilsweet

2
  • Soporte de múltiples entradas con el mismo nombre (las casillas de verificación generalmente hacen esto).
  • selectores caché cuando posibles
  • valores de retorno de todas las entradas, si checkbox o radio no está establecido, el valor es null
  • Desactiva checkbox o radio si el valor es null

    $.fn.formData = function(values) { 
     
        var form = $(this); 
     
        var inputs = $(':input', form).get(); 
     
        var hasNewValues = typeof values == 'object'; 
     
    
     
        if (hasNewValues) { 
     
        $.each(inputs, function() { 
     
         var input = $(this); 
     
         var value = values[this.name]; 
     
    
     
         if (values.hasOwnProperty(this.name)) { 
     
         switch (this.type) { 
     
          case 'checkbox': 
     
          input.prop('checked', value !== null && value); 
     
          break; 
     
          case 'radio': 
     
          if (value === null) { 
     
           input.prop('checked', false); 
     
          } else if (input.val() == value) { 
     
           input.prop("checked", true); 
     
          } 
     
          break; 
     
          default: 
     
          input.val(value); 
     
         } 
     
         } 
     
        }); 
     
        return form; 
     
        } else { 
     
        values = {}; 
     
        $.each(inputs, function() { 
     
         var input = $(this); 
     
         var value; 
     
         switch (this.type) { 
     
         case 'checkbox': 
     
         case 'radio': 
     
          value = input.is(':checked') ? input.val() : null; 
     
          break; 
     
         default: 
     
          value = $(this).val(); 
     
         } 
     
         values[this.name] = value; 
     
        }); 
     
        return values; 
     
        } 
     
    };
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

Cuestiones relacionadas