¿Cómo uso form.serialize de jQuery pero excluyo campos vacíos?

107

Tengo un formulario de búsqueda con una serie de entradas de texto y menús desplegables que se envía a través de un GET. Me gustaría tener una URL de búsqueda más limpia eliminando los campos vacíos de la cadena de consulta cuando se realiza una búsqueda.

var form = $("form");  
var serializedFormStr = form.serialize();  
// I'd like to remove inputs where value is '' or '.' here
window.location.href = '/search?' + serializedFormStr

¿Alguna idea de cómo puedo hacer esto usando jQuery?

Tom Viner
fuente

Respuestas:

167

He estado revisando los documentos de jQuery y creo que podemos hacer esto en una línea usando selectores :

$("#myForm :input[value!='']").serialize() // does the job!

Obviamente, #myForm obtiene el elemento con id "myForm", pero lo que fue menos obvio para mí al principio fue que el carácter de espacio es necesario entre #myForm y: input ya que es el operador descendiente .

: input coincide con todos los elementos input, textarea, select y button.

[value! = ''] es un atributo que no es igual al filtro. Lo extraño (y útil) es que todos: los tipos de elementos de entrada tienen atributos de valor, incluso selecciones y casillas de verificación, etc.

Finalmente para eliminar también las entradas donde el valor era '.' (como se menciona en la pregunta):

$("#myForm :input[value!=''][value!='.']").serialize()

En este caso, la yuxtaposición, es decir, colocar dos selectores de atributos uno al lado del otro , implica un AND. Usar una coma implica un OR. Lo siento si eso es obvio para la gente de CSS.

Tom Viner
fuente
3
@Mvision, eso se debe a que hay una omisión pequeña pero significativa en esta respuesta. Para los selectores de CSS normal / puro en jQuery 1.8 y versiones anteriores, [value]coincide con cualquier elemento con el atributo value presente , incluidos aquellos con valores vacíos (o sin valores). Esto se debe a un error en versiones anteriores de jQuery que creaba una inconsistencia entre ciertas variaciones de input[value]y :input[value]. Tomemos, por ejemplo <input value="foo"><input value=""><input value><input>,; el error se ilustra en este violín .
Noyo
4
Para mí, esto funcionó: $form.find(":input[value]")- los campos vacíos no fueron seleccionados. Esto no funcionó: $form.find(":input[value!='']")- se seleccionaron todos los campos. Espero que ayude a alguien. (jQuery 2.0.0)
Ryan Wheale
1
$form.find(":input[value]")también funcionó para mí (jQuery 1.11.0)
GSTAR
Solo funcionó si el valueatributo ya estaba allí. No lo reconoció de otra manera.
Starcorn
1
En algunos casos en los que valuese establece mediante programación, esto no funcionará ( valueno existirá como un atributo HTML, pero sí como un atributo de datos en la entrada). En esos casos, intente lo siguiente: $('#myForm :input').filter(function(i) { return ($(this).val().length != 0); }).serialize(). EDITAR: Acabo de ver la respuesta de Rich con el mismo efecto.
Fateh Khalsa
54

No pude hacer que la solución de Tom funcionara (?), Pero pude hacer esto usando .filter()una función corta para identificar campos vacíos. Estoy usando jQuery 2.1.1.

var formData = $("#formid :input")
    .filter(function(index, element) {
        return $(element).val() != '';
    })
    .serialize();
Rico
fuente
2
No se pudo obtener la respuesta aprobada, ¡pero funcionó muy bien! ¡Gracias!
bfritz
Respondiendo a mi propia pregunta: "El :inputselector básicamente selecciona todos los controles de formulario. Selecciona todos los elementos de entrada, área de texto, selección y botón". fuente
Dinei
Sí, el de Tom está roto . El tuyo también es más limpio que mi intento en ese violín. Up'd
Hashbrown
11

Esto funciona para mi:

data = $( "#my_form input").filter(function () {
        return !!this.value;
    }).serialize();
RMazitov
fuente
Bueno, la devolución de llamada permite pasar valores que devuelven verdaderos, !!vuelve a escribir cualquier cosa a bool, puedes probar en la consola. !!('test'), !!(5),!!(0)
Aiphee
2
Y en lugar de inputselector, debería :inputincluir selecciones, etc.
Aiphee
Sugiero este cambio:data = $( "#my_form :input").filter(function () { return $(this).val() != ""; }).serialize();
Mahoor13
9

Podrías hacerlo con una expresión regular ...

var orig = $('#myForm').serialize();
var withoutEmpties = orig.replace(/[^&]+=\.?(?:&|$)/g, '')

Casos de prueba:

orig = "a=&b=.&c=&d=.&e=";
new => ""

orig = "a=&b=bbb&c=.&d=ddd&e=";
new => "b=bbb&d=ddd&"  // dunno if that trailing & is a problem or not
nickf
fuente
.replace (/[^&]+=\.?(& | $) / g, '') cubre ambos casos. Pero agregaría .replace (/ & $ /, '') para eliminar el &
Tom Viner
15
No hay problema de que las expresiones regulares no puedan empeorar.
Michael Cook
3

He usado la solución anterior, pero para mí no funcionaron. Entonces he usado el siguiente código

$('#searchform').submit(function(){

            var serializedData = $(this).serializeArray();
            var query_str = '';

            $.each(serializedData, function(i,data){
                if($.trim(data['value'])){
                    query_str += (query_str == '') ? '?' + data['name'] + '=' + data['value'] : '&' + data['name'] + '=' + data['value'];
                }
            });
            console.log(query_str);
            return false;
        });

Puede ser útil para alguien

Rajan Rawal
fuente
1

Miraría el código fuente de jQuery. En la última versión de la línea 3287.

Podría agregar las funciones "serialize2" y "serializeArray2". por supuesto, nómbrelos con algo mezquino.

O la mejor manera sería escribir algo para sacar las variables no utilizadas de serializedFormStr. ¿Alguna expresión regular que busca = & en la mitad de la cadena o termina en = ¿Algún asistente de expresiones regulares alrededor?

ACTUALIZACIÓN: Me gusta más la respuesta de rogeriopvl (+1) ... especialmente porque no puedo encontrar ninguna buena herramienta de expresiones regulares en este momento.

BuddyJoe
fuente
1

Una alternativa a la solución de Rich :

$('#form').submit(function (e) {
  e.preventDefault();

  var query = $(this).serializeArray().filter(function (i) {
    return i.value;
  });

   window.location.href = $(this).attr('action') + (query ? '?' + $.param(query) : '');
});

Explicaciones:

  • .submit()se engancha al submitevento del formulario
  • e.preventDefault() evita que el formulario se envíe
  • .serializeArray() nos da una representación de matriz de la cadena de consulta que se iba a enviar.
  • .filter() elimina los valores falsos (incluidos los vacíos) en esa matriz.
  • $.param(query) crea una representación serializada y compatible con URL de nuestra matriz actualizada
  • establecer un valor para window.location.hrefenviar la solicitud
Kathandrax
fuente
0

En coffeescript, haz esto:

serialized_form = $(_.filter($(context).find("form.params input"), (x) -> $(x).val() != '')).serialize()
John Goodsen
fuente
-1

Es posible que desee ver la función jquery .each (), que le permite iterar a través de cada elemento de un selector, de esta manera puede verificar cada campo de entrada y ver si está vacío o no y luego eliminarlo del formulario usando element.remove (). Después de eso, puede serializar el formulario.

rogeriopvl
fuente
1
El único problema con eso es que el usuario verá desaparecer los controles vacíos justo antes de que se envíe la página. Sería mejor establecer el nombre en "" para que serializar lo ignore.
Tom Viner