Hi all,

I posted up a thread a few weeks ago, regarding automatically updating a drop down list from a database using ajax.

Someone posted a reply suggesting i use the w3schools website for some help and i managed to put together something that worked for me.

However, i'm now coming across a problem where i need to use the ajax feature more than once on the same page.

I'll try post a link to give a sort of working example and i'll also try explain myself.

At the moment i have 4 select boxes:

Category
Sub Category

Manufacturer
Model

What happens, if i select a value from the Category list, the model list gets updated.

But what should happen is, Category updates sub category and then manufacturer updates model.

If i choose a value from manufacturer first, the model list updates correctly.

So as you can see it's kinda half working.

What i've been doing is calling two different .js files and using 2 different onChange events, hoping that it would update how i wanted it to.

<select name="cat_id" class="input" id="cat_id" onchange="subcatUpdate(this.value)">
<select name="man_id" class="input" id="man_id" onchange="modelUpdate(this.value)">

Below is a copy of my 2 .js files

var xmlhttp;

function subcatUpdate(str)
{
xmlhttp=GetXmlHttpObject();
if (xmlhttp==null)
  {
  alert ("Browser does not support HTTP Request");
  return;
  }
var url="update_subcat.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)
{
document.getElementById("subcat_id").innerHTML=xmlhttp.responseText;
}
}

function GetXmlHttpObject()
{
if (window.XMLHttpRequest)
  {
  // code for IE7+, Firefox, Chrome, Opera, Safari
  return new XMLHttpRequest();
  }
if (window.ActiveXObject)
  {
  // code for IE6, IE5
  return new ActiveXObject("Microsoft.XMLHTTP");
  }
return null;
}
var xmlhttp;

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

function stateChanged()
{
if (xmlhttp.readyState==4)
{
document.getElementById("happy_id").innerHTML=xmlhttp.responseText;
}
}

function GetXmlHttpObject()
{
if (window.XMLHttpRequest)
  {
  // code for IE7+, Firefox, Chrome, Opera, Safari
  return new XMLHttpRequest();
  }
if (window.ActiveXObject)
  {
  // code for IE6, IE5
  return new ActiveXObject("Microsoft.XMLHTTP");
  }
return null;
}

And finally my HTML/PHP Code

<table width="54%" cellpadding="5" cellspacing="5" class="table_style">
  <tr>
    <td width="21%"><label>Category:<br />
      <select name="cat_id" class="input" id="cat_id" onchange="subcatUpdate(this.value)">
          <option value="Please Select">Please Select</option>
      <?php
      		  // Open Connection to DB
			  require_once ('../include/config.inc_admin.php');
			  require_once (MYSQL);
			  
			  $q = "SELECT cat_id, cat_name FROM categories";
			  $r = mysqli_query ($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));
			  
			  while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
			  	
				echo "<option value=" . $row['cat_id'] . ">" . $row['cat_name'] . "</option>"; 
			  }
      ?>
        </select></label></td>
    </tr>
  <tr>
    <td><label>Sub Category:<br />
    </label><div id="subcat_id"></div></td>
  </tr>
  <tr>
    <td><label>Manufacturer:<br />
        <select name="man_id" class="input" id="man_id" onchange="modelUpdate(this.value)">
          <option value="Please Select">Please Select</option>
          <?php
			  
			  $q = "SELECT man_id, manufacturer FROM manufacturers";
			  $r = mysqli_query ($dbc, $q) or trigger_error("Query: $q\n<br />MySQL Error: " . mysqli_error($dbc));
			  
			  while ($row = mysqli_fetch_array($r, MYSQLI_ASSOC)) {
			  	
			  	$man_id = $row['man_id'];
				echo "<option value=" . $row['man_id'] . ">" . $row['manufacturer'] . "</option>"; 
			  }
      ?>
        </select>
    </label></td>
  </tr>
  <tr>
    <td><label>Model:<br />
    </label><div id="happy_id"></div></td>
  </tr>

I've left out my php files for connecting to the database as i know these are functioning okay.

Is the method i'm usin the correct way to be going about it or am i missing something out which is causing me to have this problem?

Any help is greatly appreciated,

Regards,

Dan

Member Avatar

diafol

So, in short what are you trying to achieve, chaining 4 dropdowns [cat -> subcat -> manuf -> model] OR simply 2 X 2 chains [cat -> subcat AND manuf -> model]?

So, in short what are you trying to achieve, chaining 4 dropdowns [cat -> subcat -> manuf -> model] OR simply 2 X 2 chains [cat -> subcat AND manuf -> model]?

Hi,

Sorry if you did not understand me before, what i'm trying to do is the user will select a cat from the list and the subcat list will appear, populated with results from the DB, then they choose a manuf and then same happens again wit the models.

So in essence yes 2 x 2 chains

Any chance you could help with that?

Regards,

Dan.

Member Avatar

diafol

OK first of all, this used to happen to me all the time before getting to grips with prototype.js (prototypejs.org). A workaround that I used to use was something like:

xmlhttp=GetXmlHttpObject(); for one function

xmlhttp2=GetXmlHttpObject2(); for another function

functions: GetXmlHttpObject() and another one called GetXmlHttpObject2()

This is obviously a wrong approach, but did the job (I think - it was a long time ago).

This is the reason I went with a js library as messing with the ajax object really annoyed me. Using prototype, conducting html updates is sooooo simple (as with other librearies, such as jQuery).

One solution:

Place the following code in a js file as reference it in the head area along with the prototype.js file.

function updateDD(dd){
  if(dd == 'man'){
      var param = "man=" + $F('man_id').value;    
      var tag_id = 'model_id';
  }else{
      var param = "cat="  + $F('cat_id').value;    
      var tag_id = 'subcat_id';
  }
  var url = "/includes/popDrops.php";
  var model = new Ajax.Updater(tag_id, url,{method: 'post',parameters: param});
}

Change your onchange attribute value in the man_id and cat_id select tag to:

onchange="updateDD('man');" and onchange="updateDD('cat');" respectively.


Your php include file (/includes/popDrops.php) will now receive a $_POST variable, which is either $_POST or $_POST.

You can then use:

//db connection info


if(isset($_POST['cat'])){
 $sql = mysql_query("...");
}elseif(isset($_POST['man'])){
 $sql = mysql_query("...");
}

while($data = mysql_fetch_array($sql)){
   echo "\n\t<option value=\"$r[0]\">{$r['name']}</option>";
}
//NOTE - only if 'name' is common field to both tables (model and subcat)

NOT TESTED - top of head thingy.

Do it with jquery or prototype ... they are easy to use ...

Hi,

thanks for the solution ardav! i'll give that a try today sometime and keep you posted on how it goes.

Much apprecaited!

Regards,

Dan

I'm with Ardav on using a framework for your JS / Ajax requests. It does pay to write out your scripts the long way in the beginning when you are learning just to get a feel for what the script is doing but you can literally turn this:

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

Into this:

function subcatUpdate(id, url)
{
     new Ajax.Updater(id,url,{asynchronous:true}); 
}

Big difference and a HUGE time saver.

The nice part is that if it is a "generic" request you can use function subcatUpdate(id, url) for as many Ajax requests as you want to by simply changing the id and url in your 'onclick'.

I swear by Prototype.js and it might be worth it for you to look into.

Hi everyone,

update on this post, sorry its been a while, been very busy!

Tried the code posted by ardav and tweaked it slighty to my needs and works spot on!

thanks very much, to all of you that contirbuted!

And i can deifinately see the advantages of using a framework such as prototype, as CFROG pointed out, the difference in the code size etc was clear to see!

Regards,

Dan