SitePoint Sponsor

User Tag List

Results 1 to 10 of 10
  1. #1
    SitePoint Evangelist pompopom's Avatar
    Join Date
    Feb 2004
    Location
    Huldenberg (Belgium)
    Posts
    426
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    HTML array + AJAX

    Hi,

    I have a some php code that creates an HTML form with some arrays:
    PHP Code:
    <input class="ins_opd" id="opdracht_titel" name="opdracht_titel['.$opdracht.']" type="text"  value="'.$gegevens['opdracht'].'" />
    <
    input class="ins_punt" id="punt" name="punt['.$opdracht.']" type="text" value="'.$gegevens['punt'].'" /> 
    the $opdracht is a php variable and consists of a number. The reason why it's an array because the above code is iterated in a foreach loop and $opdracht is in every iteration a different value.

    I'm expecting to receive 2 arrays: opdracht_titel[] and punt[], with each one, as many values as iterations, and with an arraykey = $opdracht.

    in the JS part of the AJAX I do:
    Code:
    var titel = document.getElementsByName("opdracht_titel[]");
    var punt = document.getElementsByName("punt[]");
    And pass titel and punt to a background script in php. (with an xmlhttpRequest => POST)
    However the closest I get (besides errors, undefined, empty array, ...) when doing a var_dump in the receiving php script is:
    Code:
    array(2) { ["titel"]=>  string(23) "[object HTMLCollection]" ["punt"]=>  string(23) "[object HTMLCollection]" }
    which is IMHO a step in the right direction, but I must be missing something, somewhere...

    Can anyone shed a light onto this one?

    thx.
    The Path of excess leeds to the tower of wisdom (W. Blake)

  2. #2
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,705
    Mentioned
    102 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by pompopom View Post
    Can anyone shed a light onto this one?
    getElementsByName gives you an html collection, which is an array-like object. You would need to specify the first item from that collection to get the actual input, and then to ge the value of that input field.

    For example:
    Code javascript:
    var titel = document.getElementsByName("opdracht_titel[]")[0].value;

    However, I would prefer to access the form fields via the form instead.

    Code javascript:
    var form = document.getElementById('jobapplication'),
        titel = form.elements['opdracht_titel[]'].value;

    However, you are using an ajax process to send the form data to the php script, so you can do that without needing to deal with any of the form fields.

    For example:

    Code javascript:
    function success(data) {
       // do stuff with data from php
       alert(data);
    };
     
    $.post("test.php", $("#jobapplication").serialize(), success);
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  3. #3
    SitePoint Evangelist pompopom's Avatar
    Join Date
    Feb 2004
    Location
    Huldenberg (Belgium)
    Posts
    426
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Hi Paul,

    Thx for your time.

    I immediately tried your suggestions.

    First option
    Gives me following error in Firebug:
    document.getElementsByName("opdracht_titel[]")[0] is undefined
    http://localhost:8080/includes/js/co...x1352808166.js
    Line 160

    2nd option
    Same error
    form.elements['opdracht_titel[]'] is undefined

    Note: I changed my html code to:
    Code:
    <form name="koen" id="koen">
    As you declared a var from with getElementById('koen'), ...

    3rd Option
    If I understand correctly that is javascript code to process data FROM php? I need to get the html array into javascript (AJAX) and posted to PHP.
    The Path of excess leeds to the tower of wisdom (W. Blake)

  4. #4
    SitePoint Evangelist pompopom's Avatar
    Join Date
    Feb 2004
    Location
    Huldenberg (Belgium)
    Posts
    426
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    UPDATE:
    Code:
    var titel = document.getElementById("opdracht_titel").value;
    var type = document.getElementById("type").value;
    var punt = document.getElementById("punt").value;
    postvars="rapport="+rapport+"&klas="+klas+"&titel[]="+titel+"&type[]="+type+"&punt[]="+punt;
    postvars is a variable that is used for the xmlhttp request and are basically the variables to sent to the php script.

    previously I did not add the [] is that string. Which resulted in not having an array php side. Adding the [] results now in:
    Code:
    array(5) { ["rapport"]=>  string(1) "1" ["klas"]=>  string(2) "32" ["titel"]=>  array(1) { [0]=>  string(22) "Schrijven: Wie ben ik?" } ["type"]=>  array(1) { [0]=>  string(1) "2" } ["punt"]=>  array(1) { [0]=>  string(2) "10" } }
    Mind the 3 arrays nested in the $_POST array. The above code however is only sending the first array element... Think gonna rework now with info from Paul.

    Bottom line: on the right track, but have not passed the finish (yet)
    The Path of excess leeds to the tower of wisdom (W. Blake)

  5. #5
    SitePoint Evangelist pompopom's Avatar
    Join Date
    Feb 2004
    Location
    Huldenberg (Belgium)
    Posts
    426
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    To whom it may concern:
    The usual FORM-element array with <input>'s named "xyz[someindexname]" cannot be used when passing them to javascript.

    Why? Javascript itself creates automatically an array from <input> fields that have the same name. So you just call them "xyz". Or javascript chokes on the []. The use of associative array indexes (HTML-level) is however ruled out by this behaviour.

    Don't know if this is exactly the truth, but it's what I have found out these days.

    So in my case how have I dealt with it:
    Added a hidden input field which contains $opdracht value. So that array will store the associative index keys.
    HTML Code:
    <form id="editrapport" name="editrapport">
    									<fieldset class="editrapport">
    										<legend>Bewerk rapport:</legend>
    										<table class="editrapport">
    										  <tbody><tr>
    										    <!-- <th>Volgorde:</th> -->
    										    <th>Type:</th>
    										    <th>Nr:</th>
    										    <th>Titel:</th>
    										    <th>Punt:</th>
    										  </tr><tr><td class="types">
    						<select id="type" name="type" class="ins_type">
    							<option value="1">
    								Kleine overhoring (KO)
    						   </option><option value="4">
    								Leesoefening (LS)
    						   </option><option value="3">
    								Synthese proef (SP)
    						   </option><option selected="" value="2">
    								Taak (TK)
    						   </option>
    						</select>
    					</td>
    					<td class="nummer">
    						1
    					</td>
    					<td class="opdrachten">
    						<input type="text" value="Schrijven: Wie ben ik?" onkeyup="SearchSuggestions(32,1,this.value);" name="opdracht_titel" id="opdracht_titel" class="ins_opd">
    						<div style="display: none;" id="autosug"></div>
    					</td>
    					<td class="punten">
    						<input type="text" value="10" name="punt" id="punt" class="ins_punt">
    					</td>
    					<input type="hidden" value="1" name="opdracht" id="opdracht">					
    				</tr><tr><td class="types">
    						<select id="type" name="type" class="ins_type">
    							<option selected="" value="1">
    								Kleine overhoring (KO)
    						   </option><option value="4">
    								Leesoefening (LS)
    						   </option><option value="3">
    								Synthese proef (SP)
    						   </option><option value="2">
    								Taak (TK)
    						   </option>
    						</select>
    					</td>
    					<td class="nummer">
    						1
    					</td>
    					<td class="opdrachten">
    						<input type="text" value="Schooltaalwoorden" onkeyup="SearchSuggestions(32,1,this.value);" name="opdracht_titel" id="opdracht_titel" class="ins_opd">
    						<div style="display: none;" id="autosug"></div>
    					</td>
    					<td class="punten">
    						<input type="text" value="10" name="punt" id="punt" class="ins_punt">
    					</td>
    					<input type="hidden" value="2" name="opdracht" id="opdracht">					
    				</tr><tr><td class="types">
    						<select id="type" name="type" class="ins_type">
    							<option value="1">
    								Kleine overhoring (KO)
    						   </option><option selected="" value="4">
    								Leesoefening (LS)
    						   </option><option value="3">
    								Synthese proef (SP)
    						   </option><option value="2">
    								Taak (TK)
    						   </option>
    						</select>
    					</td>
    					<td class="nummer">
    						1
    					</td>
    					<td class="opdrachten">
    						<input type="text" value="Nieuwsbegrip" onkeyup="SearchSuggestions(32,1,this.value);" name="opdracht_titel" id="opdracht_titel" class="ins_opd">
    						<div style="display: none;" id="autosug"></div>
    					</td>
    					<td class="punten">
    						<input type="text" value="15" name="punt" id="punt" class="ins_punt">
    					</td>
    					<input type="hidden" value="3" name="opdracht" id="opdracht">					
    				</tr></tbody></table>
    				</fieldset>
    				<fieldset class="submit">
    					<button onclick="SaveChangesRapport(32,1);" name="submit" type="button" class="forms">
    						<img src="/pics/lco_save.png">
    						Opslaan
    					</button>
    					<button name="reset" type="reset" class="forms">
    						<img src="/pics/lco_reload.png">
    						Herstellen
    					</button>
    					<button onclick="GetRapport(32,1);" name="cancel" type="button" class="forms">
    						<img src="/pics/lco_nokay.png">
    						Annuleren
    					</button>
    				</fieldset>
    			</form>
    Notice the reoccuring sequence of <input> fields with the same name property. (background info: the form is dynamic so based on database content this can imply more sequences of the same fields, or less)

    Then in javascript I do:
    Code:
    var form = document.getElementById('editrapport');
    var posttitel="";
    var posttype="";
    var postpunt="";
    var postopdracht="";
    for(i=0;i < form.elements['opdracht_titel'].length;i++){
    	posttitel = posttitel+"&titel[]="+form.elements['opdracht_titel'][i].value;
    }
    for(i=0;i < form.elements['type'].length;i++){
    	posttype = posttype+"&type[]="+form.elements['type'][i].value;
    }
    for(i=0;i < form.elements['punt'].length;i++){
    	postpunt = postpunt+"&punt[]="+form.elements['punt'][i].value;
    }
    for(i=0;i < form.elements['opdracht'].length;i++){
    	postopdracht = postopdracht+"&opdracht[]="+form.elements['opdracht'][i].value;
    }	
    postvars="rapport="+rapport+"&klas="+klas+posttitel+posttype+postpunt+postopdracht;
    and post it with xmlhttp resulting on php side in:
    Code:
    array(6) { ["rapport"]=>  string(1) "1" ["klas"]=>  string(2) "32" ["titel"]=>  array(3) { [0]=>  string(22) "Schrijven: Wie ben ik?" [1]=>  string(17) "Schooltaalwoorden" [2]=>  string(12) "Nieuwsbegrip" } ["type"]=>  array(3) { [0]=>  string(1) "2" [1]=>  string(1) "1" [2]=>  string(1) "4" } ["punt"]=>  array(3) { [0]=>  string(2) "10" [1]=>  string(2) "10" [2]=>  string(2) "15" } ["opdracht"]=>  array(3) { [0]=>  string(1) "1" [1]=>  string(1) "2" [2]=>  string(1) "3" } }
    Which is as expected.

    I'm still open for suggestions on how to do it better, but this seems to work.
    The Path of excess leeds to the tower of wisdom (W. Blake)

  6. #6
    SitePoint Evangelist pompopom's Avatar
    Join Date
    Feb 2004
    Location
    Huldenberg (Belgium)
    Posts
    426
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    me again...

    Above code works perfectly IF there are multiple rows on the form. However when code is called with only one row, thus not providing an array to the JS function it fails (i.e. there are no arrays passed to the php code)

    Unfortunately there seems no such thing as is_array() in javascript as I know from PHP. Also Array.isArray seems to give me an alert that "no such function exist" alltough Google seems to be fairly confident in it's existence...

    Is there an "easy way" to check if an object is an array (applicable to the JS code in my previous post)?
    The Path of excess leeds to the tower of wisdom (W. Blake)

  7. #7
    SitePoint Evangelist pompopom's Avatar
    Join Date
    Feb 2004
    Location
    Huldenberg (Belgium)
    Posts
    426
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Changed my code to:
    Code:
    	if(typeof form.elements['opdracht_titel'].value == "string"){
    		posttitel = "&titel="+document.getElementById("opdracht_titel").value;
    		posttype = "&type="+document.getElementById("type").value;
    		postpunt = "&punt="+document.getElementById("punt").value;
    		postopdracht = "&opdracht="+document.getElementById("opdracht").value;
    	}
    	else{
    		for(i=0;i < form.elements['opdracht_titel'].length;i++){
    			posttitel = posttitel+"&titel[]="+form.elements['opdracht_titel'][i].value;
    		}
    		for(i=0;i < form.elements['type'].length;i++){
    			posttype = posttype+"&type[]="+form.elements['type'][i].value;
    		}
    		for(i=0;i < form.elements['punt'].length;i++){
    			postpunt = postpunt+"&punt[]="+form.elements['punt'][i].value;
    		}
    		for(i=0;i < form.elements['opdracht'].length;i++){
    			postopdracht = postopdracht+"&opdracht[]="+form.elements['opdracht'][i].value;
    		}
    	}
    Is this a good alternative? typeof returns "undefined" when submitting an array. Don't know if using typeof this way might cause other issues...

    BTW: it seems to work.
    The Path of excess leeds to the tower of wisdom (W. Blake)

  8. #8
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,705
    Mentioned
    102 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by pompopom View Post
    Is this a good alternative? typeof returns "undefined" when submitting an array. Don't know if using typeof this way might cause other issues...
    Why are you manually creating the URL? jQuery has the serialize() method that automatically does all of that hard work for you.

    Code javascript:
    function success(data) {
       // do stuff with data from php
       alert(data);
    };
     
    $.post("test.php", $("#jobapplication").serialize(), success);

    The last line posts an ajax request to the php page, and the success function handles any reponse from the php page. The success part is completely optional though.
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript

  9. #9
    SitePoint Evangelist pompopom's Avatar
    Join Date
    Feb 2004
    Location
    Huldenberg (Belgium)
    Posts
    426
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Quote Originally Posted by paul_wilkins View Post
    Why are you manually creating the URL? jQuery has the serialize() method that automatically does all of that hard work for you.

    Code javascript:
    function success(data) {
       // do stuff with data from php
       alert(data);
    };
     
    $.post("test.php", $("#jobapplication").serialize(), success);

    The last line posts an ajax request to the php page, and the success function handles any reponse from the php page. The success part is completely optional though.
    That's because I don't use jQuery, just plain Javascript.
    The Path of excess leeds to the tower of wisdom (W. Blake)

  10. #10
    Unobtrusively zen silver trophybronze trophy
    paul_wilkins's Avatar
    Join Date
    Jan 2007
    Location
    Christchurch, New Zealand
    Posts
    14,705
    Mentioned
    102 Post(s)
    Tagged
    4 Thread(s)
    Quote Originally Posted by pompopom View Post
    That's because I don't use jQuery, just plain Javascript.
    Ahh, then let's take care of things in a more flexible and less labour intensive manner.

    You're going to want to first serialize the form elements in to an object, and to then use JSON.stringify(serialized) to turn that object in to data that AJAX can easily send.

    Code javascript:
    var form = document.getElementById('editrapport'),
        serialized = serializeForm(form.elements),
        stringified = JSON.stringify(serialized);

    Serializing the form is quite easy.

    Code javascript:
    function serializeForm(obj) {
        var serialized = {},
            prop;
        for (prop in obj) {
            if (obj.hasOwnProperty(prop)) {
                serialized = serializeField(obj[prop], serialized);
            }
        }
        return serialized;
    }

    When serializing a field, we want to use the field name as the key.

    If the object already has a property of that name, and it isn't already an array, we can convert it in to one before adding the new value to it.

    Code javascript:
    function serializeField(field, target) {
        var value = field.value;
        if (!value) {
            return target;
        }
        if (field.name) {
            if (target.hasOwnProperty(field.name)) {
                if (!Array.isArray(target[field.name])) {
                    target[field.name] = [target[field.name]];
                }
                target[field.name].push(value);
            } else {
                target[field.name] = value;
            }
        }
        return target;
    }

    We can deal with compatibility issues of older web browsers by polyfilling in the isArray method if it doesn't already exist.

    Code javascript:
    if (!Array.isArray) {
        Array.isArray = function (vArg) {
            return Object.prototype.toString.call(vArg) === "[object Array]";
        };
    }

    The following shows an example of the above in action: http://jsfiddle.net/pmw57/aphJd/
    Programming Group Advisor
    Reference: JavaScript, Quirksmode Validate: HTML Validation, JSLint
    Car is to Carpet as Java is to JavaScript


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •