How do I get the values and id's of multiple select lists and pass it to AJAX?

Go To StackoverFlow.com

1

I am trying to iterate through a number of selects in a cell of a table (they are not in a form). I have a submit button when pressed is supposed to retrieve the values and id of each select list which I will pass to the server via AJAX and PHP. My table is a table of students of a course. The table contains the students name and their attendance for a lesson in the course.

This is my table on Pastebin and jsFiddle. http://pastebin.com/NvRAbC7m and http://jsfiddle.net/4UheA/

Please note that this table is entirely dynamic. The no. of rows and the info in them is dynamically driven.

This is what I'm trying to do right now with jQuery. Please excuse the logic or the complete nonsense that is my JavaScript skills. I don't actually know what I'm doing. I'm just doing trial and error.

$('#saveAttendances').live('click', function()
{
    var attendSelect = $('.attendSelect');
    var students = new Array();
    //get select list values and id. 
    for(var i in attendSelect)
    {
        students['student_id'] += attendSelect[i].id;
        students['student_id']['attedance'] += attendSelect[i].value;
        console.log(students['student_id']);
    }
    //after retrieving values, post them through ajax
    // and update the attendances of students in PHP
    $.post("",{ data: array }, function(msg)
    {
         alert(msg);
    }); 

}); 

How do I get the values and id's of each select list and pass it to AJAX?

2012-04-04 18:38
by Johnathan Au
ids should not begin with a numbe - nathanjosiah 2012-04-04 18:46
How would I find the student's id then? Where would I put it - Johnathan Au 2012-04-04 18:48
What format do you want the data passed as? An array, JSON, ... - j08691 2012-04-04 18:55
I'm not sure. Whatever is easiest I guess on the PHP side - Johnathan Au 2012-04-04 18:57
@JohnathanAu something like id-344 then access it with $('#id-'+id)nathanjosiah 2012-04-04 19:04
Argh, I've done it for entire site. This is going to be a pain to change. I didn't think about thi - Johnathan Au 2012-04-04 19:10
@JohnathanAu, no better time than now to start doing things the right way! : - maček 2012-04-04 19:16


2

Edit

If you insist on going against jQuery's grain and using invalid HTML, here's a suitable solution for you:

$(function() {
    $('button').click(function(){
       var data = $(".attendSelect").wrap('<form/>').serialize();
       $.post('process.php', data, function(response){ ... });
       return false;            
    });
});​

Worth mentioning, this example does not rely on fanciful .on() or .live() calls. However, this requires you to have the proper name attribute set on your <select> elements as described below. This also resolves your invalid numeric id attributes issue.

See it working here on jsFiddle


Original Answer

First off, some minor changes to your HTML. You need to wrap your <select> elements in a <form> tag. Using the form tag will give you access to jQuery's .serialize() method which is the exact functionality you're looking for. Personally, I'd recommend doing things the jQuery Way™ instead of implementing your own form a serialization. Why reinvent the wheel?

Next, your td have non-unique IDs. Let's update those to use a class attribute instead of an id. E.g.,

<td class="studentName">Aaron Colman</td>

Secondly, your <select> elements could benefit from a name attribute to make form processing way easier.

<select class="attendSelect" name="students[241]">
    ...

<select class="attendSelect" name="students[270]">
    ...

<select class="attendSelect" name="students[317]">
    ...

Lastly, jQuery's .serialize() is going to be your winning ticket.

​$(function() {
    $('form').submit(function(){
       $.post('process.php', $(this).serialize(), function(response){ ... });
       return false;            
    });
});​

Upon submit, the serialized string will look something like

students[241]=Late&students[270]=Absent&students[317]=default

See it working here on jsFiddle

2012-04-04 18:48
by maček
Hey, thanks but my select lists are not in a form. They're in a table so I have to iterate through each select list - Johnathan Au 2012-04-04 18:51
Then put them in a <form>. Using <select> out of a form is invalid. Plus, you get tons of added js functionality for simply wrapping them in a form. You can use .serialize() which is built in to jQuery for this specific purpose. Or you can write your own serialization method as demonstrated in these other answers. Personally, I'd go with the jQuery Way™ of doing things - maček 2012-04-04 18:57
@JohnathanAu, I've updated my post to support your no-form implementation. Please see the edit - maček 2012-04-04 19:12
Hey, how would I wrap them in a form because the select lists are in separate cells and my submit button is outside of the table - Johnathan Au 2012-04-04 19:16
@JohnathanAu wrap the whole table in a <form> element? My Original answer has a jsfiddle with a working form example. Otherwise see my edited answer and corresponding fiddle for the no-form example. (I'm still recommending my original answer as it's much better HTML; it resolves your non-unique IDs, gives name attributes to your selects, resolves your numeric id issue, and adds a valid form wrapper for your selects. - maček 2012-04-04 19:20
Yeah, if it's better then I'll have to do this. Will it not be data intensive in that it'll be sending unnecessary data i.e. the entire table to the server - Johnathan Au 2012-04-04 19:25
let us continue this discussion in chatmaček 2012-04-04 19:27


1

live() is deprecated as of jQuery 1.7, use on() instead

http://api.jquery.com/on/

students is an array, so I don't think you can do students['student_id'], if you would like to push an array of student, you can:

$('#saveAttendances').on('click', function() {
    var students = [];

    // iterate through <select>'s and grab key => values
    $('.attendSelect').function() {
        students.push({'id':$(this).attr('id'), 'val':$(this).val()});
    });

    $.post('/url.php', {data: students}, function() { // do stuff });
});

in your php:

var_dump($_POST); // see what's inside :)

As @nathan mentioned in comment, avoid using number as the first character of an ID, you can use 'student_<?php echo $id ?>' instead and in your .each() loop:

students.push({'id':$(this).attr('id').replace('student_', ''), 'val':$(this).val()});
2012-04-04 18:44
by Andreas Wong
I noticed that in console.log for my snippet, it has A LOT of undefined, 181 of them. Is that normal? It would log the id's then have a lot of undefined - Johnathan Au 2012-04-04 18:50
@JohnathanAu yes, as I said, since students is an Array, doing students[student_id] would have no effect on students, then on your students['student_id']['attedance'] += attendSelect[i].value;, it will throw undefine - Andreas Wong 2012-04-04 18:52
Ah, I see, not very nifty - Johnathan Au 2012-04-04 18:52
@NiftyDude, I think you want .attr() instead of .prop() as id is an attributemaček 2012-04-04 18:56
@JohnathanAu sorry bout that : - Andreas Wong 2012-04-04 18:56
@macek oh crap.. thanks for pointing that out : - Andreas Wong 2012-04-04 18:56
lol. I noticed the .replace(). What does that do in that chain? It's selected the select list's id then ... - Johnathan Au 2012-04-04 18:59
@NiftyDude no problem : - maček 2012-04-04 19:00
ok, since it is not recommendable to use number as id, you need to use <select id="student_5" class="attendSelect">, for example. So in my loop, since you are only interested in the 5 portion, I did a replace of student_ to nothing, which gives you 5 (which is the id). That's basically what it does - Andreas Wong 2012-04-04 19:02


1

Edit: Updated to iterate over select instead of tr.

Perhaps you want something like below,

DEMO

var $attendSelect  = $('#tutorTable tbody tr select');
var students = {};

$attendSelect.each (function () { //each row corresponds to a student               
    students[$(this).attr('id')] = $(this).val();
}); 

This would give you an object like below,

students = { '241': 'Late', '270': 'Absent', '317': 'default' };

If the above is not the desired structure then modify the .each function in the code.

For ex: For a structure like below,

students = [{ '241': 'Late'}, {'270': 'Absent'}, {'317': 'default'}];

You need to change the code a little,

 var students = [];
 ...
 ...
 students.push({$dd.attr('id'): $dd.val()});
2012-04-04 18:50
by Selvakumar Arumugam
I think you want .attr() instead of .prop() as id is an attribute - maček 2012-04-04 19:00
@macek Thanks! updated the post - Selvakumar Arumugam 2012-04-04 19:01


1

Here's jQuery that will build an object you can pass to your script:

$('button').click(function() {
    var attendance = new Object;
    $('select').each(function() {
        attendance[$(this).attr('id')] = $(':selected', this).text();
    })
});​

jsFiddle example.

This results in: {241:"Late",270:"Absent",317:"Late"}

2012-04-04 18:58
by j08691


1

var $select = $('.attendSelect'),
    students = [];
$('body').on('click', '#saveAttendances', function() {
    $select.each(function(k, v) {
        students[k] = {
            student_id : $(this).attr('id'),
            attedance  : $(this).val()
        };
    });
    console.log(students);
});
2012-04-04 19:01
by thecodeparadox
I think you want .attr() instead of .prop() as id is an attribute. You're the third person to make this mistake in this thread. What is going on in here - maček 2012-04-04 19:14
@macek thanks.thanks - thecodeparadox 2012-04-04 19:19
Ads