114

I have a search form with a number of text inputs & drop downs that submits via a GET. I'd like to have a cleaner search url by removing the empty fields from the querystring when a search is performed.

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

Any idea how I can do this using jQuery?

9 Answers 9

181

I've been looking over the jQuery docs and I think we can do this in one line using selectors:

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

Obviously #myForm gets the element with id "myForm" but what was less obvious to me at first was that the space character is needed between #myForm and :input as it is the descendant operator.

:input matches all input, textarea, select and button elements.

[value!=''] is an attribute not equal filter. The weird (and helpful) thing is that all :input element types have value attributes even selects and checkboxes etc.

Finally to also remove inputs where the value was '.' (as mentioned in the question):

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

In this case juxtaposition, ie placing two attribute selectors next to each other, implies an AND. Using a comma implies an OR. Sorry if that's obvious to CSS people!

Sign up to request clarification or add additional context in comments.

7 Comments

@Mvision, that's because there's a small but significant omission in this answer. For normal/pure CSS selectors in jQuery 1.8 and earlier, [value] matches any element with the attribute value present, including those with empty values (or no) values. This is due to a bug in earlier jQuery versions that created an inconsistency between certain variations of input[value] and :input[value]. Take, for example, <input value="foo"><input value=""><input value><input>; the bug is illustrated in this fiddle.
For me, this worked: $form.find(":input[value]") - empty fields were not selected. This did not work: $form.find(":input[value!='']") - all fields were selected. Hope that helps someone. (jQuery 2.0.0)
$form.find(":input[value]") also worked for me (jQuery 1.11.0)
In some cases where value is set programmatically, this won't work (value won't exist as an HTML attribute, but will as a data attribute on the input). In those cases, try this: $('#myForm :input').filter(function(i) { return ($(this).val().length != 0); }).serialize(). EDIT: Just saw Rich's answer to the same effect.
Amazing ... so simple. For me it worked very well with this for all hidden inputs $("#my-form :input:visible").serialize()
|
68

I wasn't able to get Tom's solution to work (?), but I was able to do this using .filter() with a short function to identify empty fields. I'm using jQuery 2.1.1.

var formData = $("#formid :input")
    .filter(function(index, element) {
        return $(element).val() != '';
    })
    .serialize();

3 Comments

Couldn't get the approved answer to work, but this worked great! Thanks!
Answering my own question: "The :input selector basically selects all form controls. Selects all input, textarea, select and button elements." source
Yeah, Tom's is broken. Yours is cleaner than my attempt in that fiddle too. Up'd
11

You could do it with a regex...

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

Test cases:

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

2 Comments

.replace(/[^&]+=\.?(&|$)/g, '') covers both cases. But I'd add .replace(/&$/, '') to remove the trailing &
There is no problem that regex can't make worse.
11

This works for me:

data = $( "#my_form input").filter(function () {
        return !!this.value;
    }).serialize();

3 Comments

Well, callback is letting pass values returning true, !! retypes anything to bool, you can try in console. !!('test'), !!(5), !!(0)
And instead of input selector, there should be :input to include selects, etc.
I suggest this change: data = $( "#my_form :input").filter(function () { return $(this).val() != ""; }).serialize();
3

I have used above solution but for me those did not worked. So I have used following code

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

May be useful for someone

Comments

2

An alternative to Rich's solution:

$('#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) : '');
});

Explanations:

  • .submit() hooks onto the form's submit event
  • e.preventDefault() prevents the form from submitting
  • .serializeArray() gives us an array representation of the query string that was going to be sent.
  • .filter() removes falsy (including empty) values in that array.
  • $.param(query) creates a serialized and URL-compliant representation of our updated array
  • setting a value to window.location.href sends the request

Comments

1

I would look at the source code for jQuery. In the latest version line 3287.

I might add in a "serialize2" and "serializeArray2" functions. of course name them something meaniful.

Or the better way would be to write something to pull the unused vars out of the serializedFormStr. Some regex that looks for =& in mid string or ending in = Any regex wizards around?

UPDATE: I like rogeriopvl's answer better (+1)... especially since I can't find any good regex tools right now.

Comments

0

In coffeescript, do this:

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

Comments

-1

You might want to look at the .each() jquery function, that allows you to iterate through every element of a selector, so this way you can go check each input field and see if it's empty or not and then remove it from the form using element.remove(). After that you can serialize the form.

1 Comment

The only problem with that is the user will see the empty from controls disappearing just before the page submits. Would be better to set the name to "" so serialize ignores it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.