51

I was just wondering what the best way of looping through all the child elements of a form would be? My form contains both input and select elements.

At the moment I have:

success: function(data) {
                $.each(data.details, function(datakey, datavalue) {
                    $('#new_user_form > input').each(function(key, value) {
                        if($(this).attr('id') == datakey) {
                            $(this).val(datavalue);
                        }
                    });
                });
            }

This only loops through the input elements of the form though and I want to include the select elements too:

I have tried:

$('#new_user_form > input, #new_user_form > select').each(function(key, value) {

but this doesn't work. Does anyone know why this would be happening? Thanks!

James
  • 2,800
  • 7
  • 45
  • 81

10 Answers10

86

From the jQuery :input selector page:

Because :input is a jQuery extension and not part of the CSS specification, queries using :input cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. To achieve the best performance when using :input to select elements, first select the elements using a pure CSS selector, then use .filter(":input").

This is the best choice.

$('#new_user_form *').filter(':input').each(function(){
    //your code here
});
Community
  • 1
  • 1
Ohgodwhy
  • 49,779
  • 11
  • 80
  • 110
27

pure JavaScript is not that difficult:

for(var i=0; i < form.elements.length; i++){
    var e = form.elements[i];
    console.log(e.name+"="+e.value);
}

Note: because form.elements is a object for-in loop does not work as expected.

Answer found here (by Chris Pietschmann), documented here (W3S).

Zanshin13
  • 980
  • 4
  • 19
  • 39
20
$('#new_user_form').find('input').each(function(){
   //your code here
});
Adarsh Raj
  • 291
  • 1
  • 7
  • 15
    This does actually work. If you want to get selects and textareas as well: $('#new_user_form').find('input, textarea, select').each(function(){ //your code here }); – mpemburn Dec 18 '13 at 10:36
13

As taken from the #jquery Freenode IRC channel:

$.each($(form).serializeArray(), function(_, field) { /* use field.name, field.value */ });

Thanks to @Cork on the channel.

Bob Stein
  • 16,271
  • 10
  • 88
  • 101
Sai Krishna
  • 7,647
  • 6
  • 29
  • 40
  • This is a perfect solution if you have a listener for all forms. This is my case: `$('body').on('submit','form',function(e) { e.preventDefault(); $.each($(this).serializeArray(),function(counter,object) { console.log(object) }); });` Thanks! – Bird87 ZA Jul 02 '15 at 09:03
  • 1
    The first parameter of the callback is the index so it should be: `$.each($(form).serializeArray(), function(index, field) {});` Still Upvoting :) – Tim Ramsey Mar 03 '16 at 13:44
8

I'm using:

$($('form').prop('elements')).each(function(){
    console.info(this)
});

It Seems ugly, but to me it is still the better way to get all the elements with jQuery.

tread
  • 10,133
  • 17
  • 95
  • 170
romuleald
  • 1,406
  • 16
  • 31
4

I have found this simple jquery snippet, to be handy for choosing just the type of selectors I want to work with:


$("select, input").each(function(){
     // do some stuff with the element
});
Orlando Herrera
  • 3,481
  • 1
  • 34
  • 44
Phil
  • 41
  • 1
3

What happens, if you do this way:-

$('#new_user_form input, #new_user_form select').each(function(key, value) {

Refer LIVE DEMO

Siva Charan
  • 17,940
  • 9
  • 60
  • 95
1

$('#new_user_form :input') should be your way forward. Note the omission of the > selector. A valid HTML form wouldn't allow for a input tag being a direct child of a form tag.

scottlimmer
  • 2,230
  • 1
  • 22
  • 29
  • An `input` tag can't be a direct child of a `form` tag? – aioobe Jul 30 '18 at 19:41
  • 2
    @aioobe Technically the spec requires that the direct ancestor be an element that accepts phrasing content. The
    spec specifies that a direct descendant be of type flow content. In other words, they need one of https://developer.mozilla.org/en-US/docs/Web/Guide/HTML/Content_categories#Phrasing_content#Flow_content between. https://developer.mozilla.org/en-US/docs/Web/HTML/Element/form https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
    – scottlimmer Aug 20 '18 at 02:02
  • Interesting. I had no idea about that. – aioobe Aug 20 '18 at 07:56
  • @scoota269 Hmm.. I wonder if that was a categorization mistake. Mozilla's form examples clearly show inputs as direct descendants of forms.. And input is also a flow element.. – Gerard ONeill Mar 28 '19 at 20:59
  • @scoota269 Just saw that Label also has the same restriction that input does. It looks like phrasing content is a subset of flow content.. with a few extra elements that can only contain phrasing content.. – Gerard ONeill Mar 29 '19 at 15:32
0

Do one of the two jQuery serializers inside your form submit to get all inputs having a submitted value.

var criteria = $(this).find('input,select').filter(function () {
    return ((!!this.value) && (!!this.name));
}).serializeArray();

var formData = JSON.stringify(criteria);

serializeArray() will produce an array of names and values

0: {name: "OwnLast", value: "Bird"}
1: {name: "OwnFirst", value: "Bob"}
2: {name: "OutBldg[]", value: "PDG"}
3: {name: "OutBldg[]", value: "PDA"}

var criteria = $(this).find('input,select').filter(function () {
    return ((!!this.value) && (!!this.name));
}).serialize();

serialize() creates a text string in standard URL-encoded notation

"OwnLast=Bird&OwnFirst=Bob&OutBldg%5B%5D=PDG&OutBldg%5B%5D=PDA"

Gregory Bologna
  • 270
  • 1
  • 6
  • 20
0

To iterate through all the fields, you have to also specify type of a field or it will ignore select and textarea and others,

$('#formID').find('input,textarea,select').each(function() {
      //Do your stuff here
    });

enjoy ;)

Umesh Patil
  • 4,668
  • 32
  • 24