Como faço para usar o form.serialize do jQuery, mas excluo campos vazios

107

Eu tenho um formulário de pesquisa com várias entradas de texto e listas suspensas que enviam por meio de um GET. Eu gostaria de ter um url de pesquisa mais limpo, removendo os campos vazios da string de consulta quando uma pesquisa é realizada.

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

Alguma ideia de como posso fazer isso usando jQuery?

Tom Viner
fonte

Respostas:

167

Estive olhando os documentos do jQuery e acho que podemos fazer isso em uma linha usando seletores :

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

Obviamente #myForm obtém o elemento com id "myForm", mas o que era menos óbvio para mim no início foi que o caractere de espaço é necessário entre #myForm e: input, pois é o operador descendente .

: entrada corresponde a todos os elementos de entrada, área de texto, seleção e botão.

[value! = ''] é um atributo diferente do filtro. O estranho (e útil) é que todos: tipos de elementos de entrada têm atributos de valor, até mesmo caixas de seleção e seleção, etc.

Finalmente, para remover também as entradas em que o valor era '.' (conforme mencionado na pergunta):

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

Nesse caso, a justaposição, ou seja, colocar dois seletores de atributos próximos um do outro , implica um AND. Usar uma vírgula implica um OR. Desculpe se isso é óbvio para o pessoal do CSS!

Tom Viner
fonte
3
@Mvision, isso é porque há uma pequena, mas significativa omissão nesta resposta. Para seletores de CSS normal / puro no jQuery 1.8 e anteriores, [value]corresponde a qualquer elemento com o atributo value presente , incluindo aqueles com valores vazios (ou nenhum). Isso se deve a um bug em versões anteriores do jQuery que criava uma inconsistência entre certas variações de input[value]e :input[value]. Tome, por exemplo <input value="foo"><input value=""><input value><input>,; o bug é ilustrado neste violino .
Noyo
4
Para mim, funcionou: $form.find(":input[value]")- campos vazios não foram selecionados. Isso não funcionou: $form.find(":input[value!='']")- todos os campos foram selecionados. Espero que ajude alguém. (jQuery 2.0.0)
Ryan Wheale
1
$form.find(":input[value]")também funcionou para mim (jQuery 1.11.0)
GSTAR de
Só funcionou se o valueatributo já estava lá. Não o reconheceu de outra forma.
Starcorn
1
Em alguns casos em que valuefor definido programaticamente, isso não funcionará ( valuenão existirá como um atributo HTML, mas como um atributo de dados na entrada). Nesses casos, tente o seguinte: $('#myForm :input').filter(function(i) { return ($(this).val().length != 0); }).serialize(). EDIT: Acabei de ver a resposta de Rich para o mesmo efeito.
Fateh Khalsa
54

Não consegui fazer a solução de Tom funcionar (?), Mas consegui fazer isso usando .filter()uma função curta para identificar campos vazios. Estou usando o jQuery 2.1.1.

var formData = $("#formid :input")
    .filter(function(index, element) {
        return $(element).val() != '';
    })
    .serialize();
Rico
fonte
2
Não foi possível fazer a resposta aprovada funcionar, mas funcionou muito bem! Obrigado!
bfritz
Respondendo minha própria pergunta: "O :inputseletor basicamente seleciona todos os controles de formulário. Seleciona todos os elementos de entrada, área de texto, seleção e botão." fonte
Dinei
Sim, o de Tom está quebrado . O seu é mais limpo do que minha tentativa naquele violino também. Up'd
Hashbrown
11

Isso funciona para mim:

data = $( "#my_form input").filter(function () {
        return !!this.value;
    }).serialize();
RMazitov
fonte
Bem, callback é deixar passar valores retornando true, !!redigitar qualquer coisa para bool, você pode tentar no console. !!('test'), !!(5),!!(0)
Aiphee
2
E em vez do inputseletor, deve haver :inputpara incluir
seleções
Sugiro esta mudança:data = $( "#my_form :input").filter(function () { return $(this).val() != ""; }).serialize();
Mahoor13
9

Você poderia fazer isso com um regex ...

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

Casos de teste:

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
fonte
.replace (/[^&]+=\.?(& | $) / g, '') cobre os dois casos. Mas eu adicionaria .replace (/ & $ /, '') para remover o &
Tom Viner
15
Não há problema que o regex não possa piorar.
Michael Cook
3

Eu usei a solução acima, mas para mim não funcionou. Usei o seguinte 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;
        });

Pode ser útil para alguém

Rajan Rawal
fonte
1

Gostaria de olhar para o código-fonte do jQuery. Na última versão da linha 3287.

Posso adicionar as funções "serialize2" e "serializeArray2". é claro que nomeie-os como algo significativo.

Ou a melhor maneira seria escrever algo para extrair os vars não utilizados de serializedFormStr. Alguma regex que procura = & no meio da string ou terminando em = Algum assistente de regex por aí?

ATUALIZAÇÃO: Eu gosto mais da resposta de rogeriopvl (+1) ... especialmente porque não consigo encontrar nenhuma boa ferramenta de regex no momento.

BuddyJoe
fonte
1

Uma alternativa para a solução 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) : '');
});

Explicações:

  • .submit()conecta-se ao submitevento do formulário
  • e.preventDefault() impede que o formulário seja enviado
  • .serializeArray() nos dá uma representação de array da string de consulta que seria enviada.
  • .filter() remove valores falsos (incluindo vazios) nessa matriz.
  • $.param(query) cria uma representação serializada e compatível com URL de nossa matriz atualizada
  • definir um valor para window.location.hrefenviar a solicitação
Kathandrax
fonte
0

No coffeescript, faça o seguinte:

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

Você pode querer olhar para a função .each () jquery, que permite iterar por cada elemento de um seletor, dessa forma, você pode verificar cada campo de entrada e ver se está vazio ou não e depois removê-lo do formulário usando element.remove (). Depois disso, você pode serializar o formulário.

rogeriopvl
fonte
1
O único problema com isso é que o usuário verá os controles vazios desaparecendo pouco antes de a página ser enviada. Seria melhor definir o nome como "" para que o serialize o ignore.
Tom Viner