Hello!
I'm having some problems with using data in an PHP form I'm working on that utilizes AJAX. Could be a beginner's mistake, but, then again, it might not be... :)

SCENARIO:
I have a form with two sets of fields, origin country, city, state, and zip, and destination country, city, state, and zip. In each set, the country drop-down is only visible (options are USA, Canada, and Mexico) until the user selects a country, after which they see a text field for city, another drop-down with a listing for all the states in the country they've selected, and a text field for zip code. Before they select a country, in place of the city, state, and zip fields, all they see is a line of text, asking the user to select a country.

The AJAX portion of the menu seems to work fine. When you select a country, the city, state, and zip fields show up, as they're supposed to. However, after filling them out, and submitting the form, it tells me that I didn't fill out the required fields of origin city, state, and country. After loading the page, and checking the source, I'm finding that, even though the page is displaying the fields, the source still thinks that the "please select a country" text is still there. So, it seems that my problem is getting the form fields to actually *insert* into the form, and not just display.

The three files I use for this are add.php, getstates.php and selectstate.js

First, here is add.php, the main form (or at least the form with as much extraneous info removed as I could):

<?php require_once('Connections/Connection.php'); ?>

$editFormAction = $_SERVER['PHP_SELF'];
if (isset($_SERVER['QUERY_STRING'])) {
  $editFormAction .= "?" . htmlentities($_SERVER['QUERY_STRING']);
}

if ((isset($_POST["MM_insert"])) && ($_POST["MM_insert"] == "form2")) {
  $insertSQL = sprintf("INSERT INTO Loads (Origin_Country, Origin_City, Origin_State, Origin_Zip, Dest_Country, Dest_City, Dest_State, Dest_Zip) VALUES (%s, %s, %s, %s, %s, %s, %s, %s)",

     GetSQLValueString($_POST['Origin_Country'], "text"),
     GetSQLValueString($_POST['Origin_City'], "text"),
     GetSQLValueString($_POST['Origin_State'], "text"),
     GetSQLValueString($_POST['Origin_Zip'], "text"),
     GetSQLValueString($_POST['Dest_Country'], "text"),
     GetSQLValueString($_POST['Dest_City'], "text"),
     GetSQLValueString($_POST['Dest_State'], "text"),
     GetSQLValueString($_POST['Dest_Zip'], "text"));

  mysql_select_db($database_Connection, $Connection);
  $Result1 = mysql_query($insertSQL, $Connection) or die(mysql_error());

  $insertGoTo = "member_profile.php";
  if (isset($_SERVER['QUERY_STRING'])) {
    $insertGoTo .= (strpos($insertGoTo, '?')) ? "&" : "?";
    $insertGoTo .= $_SERVER['QUERY_STRING'];
  }
  header(sprintf("Location: %s", $insertGoTo));
}


<html xmlns:wdg="http://ns.adobe.com/addt"><head>
<script src="selectstate.js"></script>
</head>

<body>

<table>
  <tr>
    <td>
      Origin Country:
    </td>
    <td>
      <select name="Origin_Country" onChange="showStates(this.value)">
        <option value="" selected="selected">Select country</option>
        <option value="USA">United States</option>
        <option value="CAN">Canada</option>
        <option value="MEX">Mexico</option>
       </select>
    </td>
  </tr>
  <tr>
    <td>
      <?PHP $currentrow = "Origin";?><?PHP echo $currentrow." ";?>City, State, and Zip:
    </td>
    <td>
      <div id="States">Select a country to view origin options.</div>
    </td>
  </tr>
  <tr>
    <td>
      Destination Country:
    </td>
    <td>
      <select name="Dest_Country" onChange="showStates2(this.value)">
        <option value="" selected="selected">Select country</option>
        <option value="USA">United States</option>
        <option value="CAN">Canada</option>
        <option value="MEX">Mexico</option>
       </select>
    </td>
  </tr>
  <tr>
    <td>
      <?PHP $currentrow = "Dest";?><?PHP echo $currentrow."ination ";?> City, State, and Zip:
    </td>
    <td>
      <div id="States2">Select a country to view destination options.</div>
    </td>
  </tr>
</table>
</body>
</html>

Next is getstates.php, the code that is supposed to be inserted into the form when the user selects a country (but it only seems to display the fields, not insert them into the form, so that they can be used):

<?php require_once('Connections/Connection.php'); ?>
<?php

$q=$_GET["q"];

if (!function_exists("GetSQLValueString")) {
function GetSQLValueString($theValue, $theType, $theDefinedValue = "", $theNotDefinedValue = "") 
{
  if (PHP_VERSION < 6) {
    $theValue = get_magic_quotes_gpc() ? stripslashes($theValue) : $theValue;
  }

  $theValue = function_exists("mysql_real_escape_string") ? mysql_real_escape_string($theValue) : mysql_escape_string($theValue);

  switch ($theType) {
    case "text":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;    
    case "long":
    case "int":
      $theValue = ($theValue != "") ? intval($theValue) : "NULL";
      break;
    case "double":
      $theValue = ($theValue != "") ? doubleval($theValue) : "NULL";
      break;
    case "date":
      $theValue = ($theValue != "") ? "'" . $theValue . "'" : "NULL";
      break;
    case "defined":
      $theValue = ($theValue != "") ? $theDefinedValue : $theNotDefinedValue;
      break;
  }
  return $theValue;
}
}

mysql_select_db($database_Board, $Connectin);
$query_GetStates = "SELECT States.Abbreviation FROM States WHERE States.Country = '".$q."' ORDER BY States.Abbreviation ASC";
$GetStates = mysql_query($query_GetStates, $TheBoard) or die(mysql_error());
$row_GetStates = mysql_fetch_assoc($GetStates);
$totalRows_GetStates = mysql_num_rows($GetStates);?>
<body>

<input type='text' name='<?PHP echo $currentrow;?>_City' value='' size='17' />
,

<select name='<?PHP echo $currentrow;?>_State'>
<?PHP
	do 
	{  
		echo '<option value="'.$row_GetStates['Abbreviation'].'">'.$row_GetStates['Abbreviation']."</option>";
	} while ($row_GetStates = mysql_fetch_assoc($GetStates));
  $rows = mysql_num_rows($GetStates);
  if($rows > 0) 
  {
      mysql_data_seek($GetStates, 0);
	  $row_GetStates = mysql_fetch_assoc($GetStates);
  }
?>
</select>

&nbsp;&nbsp;&nbsp;&nbsp;
 <input name='<?PHP echo $currentrow;?>_Zip'." type='text' value='' size='10' maxlength='10' />
</body>
<?PHP
mysql_free_result($GetStates);
?>

...and, finally, selectstate.js, the file that makes it all work...er...sort of...

var xmlHttp;

function showStates(str)
{ 
	xmlHttp=GetXmlHttpObject();
	if (xmlHttp==null)
 	{
 		alert ("Browser does not support HTTP Request");
 		return;
 	}
	var url="getstates.php";
	url=url+"?q="+str;
	url=url+"&sid="+Math.random();
	xmlHttp.onreadystatechange=stateChanged;
	xmlHttp.open("GET",url,true);
	xmlHttp.send(null);
}

function stateChanged() 
{ 
	if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
 	{ 
 		document.getElementById("States").innerHTML=xmlHttp.responseText;
 	} 
}

function showStates2(str2)
{ 
	xmlHttp=GetXmlHttpObject();
	if (xmlHttp==null)
 	{
 		alert ("Browser does not support HTTP Request");
 		return;
 	}
	var url2="getstates.php";
	url2=url2+"?q="+str2;
	url2=url2+"&sid="+Math.random();
	xmlHttp.onreadystatechange=stateChanged2;
	xmlHttp.open("GET",url2,true);
	xmlHttp.send(null);
}

function stateChanged2() 
{ 
	if (xmlHttp.readyState==4 || xmlHttp.readyState=="complete")
 	{ 
 		document.getElementById("States2").innerHTML=xmlHttp.responseText;
 	} 
}

function GetXmlHttpObject()
{
	var xmlHttp=null;
	try
 	{
		xmlHttp=new XMLHttpRequest(); // Firefox, Opera 8.0+, Safari
 	}
	catch (e)
 	{
 		try
  		{
  			xmlHttp=new ActiveXObject("Msxml2.XMLHTTP"); //Internet Explorer
  		}
 		catch (e)
  		{
  			xmlHttp=new ActiveXObject("Microsoft.XMLHTTP");
  		}
 	}
	return xmlHttp;
}

So, that's pretty much the long and short of it. Thanks to anyone who can assist in any way, and please let me know if there are any questions!

This is one of the two lines' that causing you all the troubles, in your <select></select> elements.

<select name="Origin_Country"onChange="showStates([b]this.value[/b] /* undefined value: since select element cannot provide value itself.*/ )">

Change the above code into this format:

<select name="Origin_Country" onchange="showStates( this.options[ this.selectedIndex ].value );">

Do the same thing with other <select></select> elements.

Hope it helps...

Thanks for the suggestion! Even though your suggestion may have pointed out a coding error on my part, unfortunately, correcting that element didn't resolve my primary issue.

When I select a country, it does properly show the drop-down of the correct states for the country listed, but, even though the page displays on the browser like it should, it's still almost as if the three fields called by the javascript aren't present in the form.

Thanks again for the suggestion, tho!

I've modified some of the lines inside your selectstate.js and converted it into a single ( showStates( "SelectID", "DivID" ) ) function to make new ajax call.

All code is as follows:
selectstate.js

var sel;
var url;
var stateChanged = function( str, div ) {
   response = xmlHttp.responseText;
   if (( xmlHttp.readyState === 4 ) || ( xmlHttp.readyState === "complete" )) {
      // if ( xmlHttp.status === 200 ) {
   /* 
TIPS:

You can also set specific action(url) to your form if both options are set, and to ensure that the form received both options value in its action(url):

   yourFormElem.action = "http://domain.com/select.php?sel1=yes&sel2=yes"
   yourFormElem.submit(); */
         div.innerHTML = response;
      // }
      }
   }; var showStates = function( str, div ) {
   div = (( document.getElementById ) ?
   document.getElementById( div ) : (( document.all ) ? document.all[ div ] : document.layers[ div ] ));
   sel = (( document.getElementById ) ?
   document.getElementById( str ) : (( document.all ) ? document.all[ str ] : document.layers[ str ] ));
   index = sel.selectedIndex;
   str = sel.options[ index ].value;
   url = (( "getstates.php?q=" + str + "&sid=" ) + Math.random() );
   xmlHttp = null;
   method = "GET";
   try {
      if ( window.XMLHttpRequest ) {
      xmlHttp = new XMLHttpRequest();
   } else if ( window.ActiveXObject ) {
         try {
         xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
         } catch( e1 ) {
         xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
         }
      }
   } catch( e2 ) {
   (( window.createRequest ) ? xmlHttp = window.createRequest() : xmlHttp = null );
   }
   (( xmlHttp.overrideMimeType ) ? xmlHttp.overrideMimeType("text/xml") : xmlHttp );
   if ( xmlHttp !== null ) {  
  xmlHttp.onreadystatechange = function() { 
   stateChanged( str, div ); 
   };      
   xmlHttp.open( method, encodeURI( url ), true );
   (( xmlHttp.setRequestHeader && method === "POST" ) ?  xmlHttp.setRequestHeader("Content-Type", "application/x-www-form-urlencoded") : xmlHttp ); 
   xmlHttp.send( null );
   } else {
      alert("\nYour browser does not support AJAX Request!"); 
   }
};

Changes inside your table select:

<table>
  <tr>
    <td>
      Origin Country:
    </td>
    <td>
      [b]<select id="Origin_Country" name="Origin_Country" onchange="showStates( 'Origin_Country', 'States' );">[/b]
        <option value="" selected="selected">Select country</option>
        <option value="USA">United States</option>
        <option value="CAN">Canada</option>
        <option value="MEX">Mexico</option>
       </select>
    </td>
  </tr>
  <tr>
    <td>
      <?PHP $currentrow = "Origin";?><?PHP echo $currentrow." ";?> City, State, and Zip:
    </td>
    <td>
      <div id="States">Select a country to view origin options.</div>
    </td>
  </tr>
  <tr>
    <td>
      Destination Country:
    </td>
    <td>
      [b]<select id="Dest_Country" name="Dest_Country" onchange="showStates( 'Dest_Country', 'States2' );">[/b]
        <option value="" selected="selected">Select country</option>
        <option value="USA">United States</option>
        <option value="CAN">Canada</option>
        <option value="MEX">Mexico</option>
       </select>
    </td>
  </tr>
  <tr>
    <td>
     <?PHP $currentrow = "Dest";?><?PHP echo $currentrow."ination ";?> City, State, and Zip:
    </td>
    <td>
      <div id="States2">Select a country to view destination options.</div>
    </td>
  </tr>
</table>

Still no dice. It seems like the AJAX/JS code is simply displaying the contents of 'getstates.php', and not literally bringing it in to the file 'add.php', which is what I need it to do, in order to insert the city, state, and zip data into the database, as per the action outlined in the form in 'add.php'.

Is it a possibility that AJAX may not be the way to go about accomplishing what I'm looking to do? My ultimate goal of this is to provide a dynamic drop-down list of states that populates based on the country that the user selects- primarily to prevent a ridiculously long and cumbersome list of all the states in 3 countries.

And, again, essential, I really appreciate your assistance with this issue. I'm trying to learn more on Javascript/Ajax while working on this, but I'm still working on grasping the basics.

Oh no... If only i could run some php code, then maybe i can provide you the exact things you need to fix your program.

Do you have any ( ajax call ), attached to onsubmit="return SomeAjaxRequestProcessor('runValue');" inside your form?

Nope...my form and submit button tags (I'm sorry I didn't include that in my initial post) are:

<form action="<?php echo $editFormAction; ?>" method="post" name="form2" id="form2">

<input type="submit" value="Add Load" /></td>
<input type="hidden" name="MM_insert" value="form2" />

'$editFormAction' references line 3 in add.php

this.options[ this.selectedIndex ].value

is exactly the same as

this.value

when applied to a select box.

In getstates.php, your do{}while(); should be just while(){}. And remove the mysql_fetch_assoc after your mysql_query call.

<input name='<?PHP echo $currentrow;?>_Zip'." type='text' value='' size='10' maxlength='10' />

Remove the ." after _Zip', so

<input name='<?PHP echo $currentrow;?>_Zip' type='text' value='' size='10' maxlength='10' />

There's a lot of other stuff. for instance, why did you write your own AJAX connection library instead of using jQuery or Prototype or something else?

Hey, ShawnCPlus,
Thanks for your suggestion- still getting the same problem, tho (after hitting 'submit', I get ""Origin_City" cannot be null" for an error response).

I did fix the PHP syntax suggestion you had with the stray '." (thanks for catching that), but I had to keep the "do{}while()" loop, as the states list wouldn't display any options using the syntax you suggested.

As for writing my own AJAX connection - to be honest, that was adapted code from another tutorial on dependant drop-downs. I copied the code, and tweaked it to work with my situation (or, I was hoping it would work! :-))

This article has been dead for over six months. Start a new discussion instead.