I have a drop down menu with categories for the user to select, and according to the one selected, i want a new drop down menu to appear containing the subcategories of the selected category. Can anybody help me with this?

    yes is something like that i'm looking for. is there a way to do that only with php? i don't really want to involve javascript into my php code.

      There are a number of ways to do this - all involving Javascript - but the most elegant way is to use AJAX. This allows the client to retrieve the new list of subcategories without reloading the entire page. I did this just the other day, actually. Here's my code; you'll need to alter the updateItems() function to fit your situation:

      <?php
      
      define( "DB_HOST", "myhostname" );
      define( "DB_NAME", "mydbname" );
      define( "DB_USER", "mydbusername" );
      define( "DB_PASS", "mydbpassword" );
      
      $dbconn = mysql_connect( DB_HOST, DB_USER, DB_PASS );
      mysql_select_db( DB_NAME, $dbconn );
      
      ?>
      
      <html>
      
      <head>
      	<title></title>
      	<script>
      
      	function HttpRequest( url ) {
      
      		var pageRequest = false // variable to hold ajax object
      	/*@cc_on
      	   @if (@_jscript_version >= 5)
      	      try {
      	      pageRequest = new ActiveXObject("Msxml2.XMLHTTP")
      	      }
      	      catch (e){
      	         try {
      	         pageRequest = new ActiveXObject("Microsoft.XMLHTTP")
      	         }
      	         catch (e2){
      	         pageRequest = false
      	         }
      	      }
      	   @end
      	@*/
      
      	if (!pageRequest && typeof XMLHttpRequest != 'undefined')
      	   pageRequest = new XMLHttpRequest()
      
      	if (pageRequest){ //if pageRequest is not false
      	   pageRequest.open('GET', url, false); //get page synchronously 
      	   pageRequest.send(null);
      	   return( embedpage(pageRequest) );
      	   }
      	}
      
      	function embedpage(request) {
      	//if viewing page offline or the document was successfully retrieved online (status code=2000)
      	if (window.location.href.indexOf("http")==-1 || request.status==200)
      	   return(request.responseText);
      	}
      
      	function updateItems() {
      		category_id = document.getElementById("categoryselect").value;
      		document.getElementById("itemselect").options[0] = new Option( "Loading...", null, true, true );
      		document.getElementById("itemselect").disabled = true;
      		// load new list
      		newselect = HttpRequest( "itemselect.php?category_id=" + category_id );
      		document.getElementById("itemselectdiv").innerHTML = newselect;
      	}
      
      </script>
      </head>
      
      <body>
      
      <form>
      
      <select name="category_id" onchange="updateItems();" id="categoryselect">
      	<option selected="selected"></option>
      	<?php
      
      	$categories = mysql_query( "select id, name from categories order by name" );
      
      	while ( $category = mysql_fetch_array( $categories ) ) {
      		echo '<option value="' . $category["id"] . '">' . $category["name"] . '</option>';	
      	}		
      
      	?>
      </select>
      
      <div id="itemselectdiv">
      <select name="item_id" id="itemselect">
      	<option></option>
      </select>
      </div>
      
      </form>
      
      </body>
      
      </html>

      When the user selects a new category, the client-side Javascript function updateItems() is triggered. This function disables the secondary <select> box and changes its text to "Loading...", so the user can't click on it until the client is done loading the new control.

      The function then invokes the AJAX functions to retrieve a page on the server called itemselect.php, passing the selected category ID in the URL; this PHP script returns an HTML <select> control containing the items within the newly selected category. Finally, updateItems() replaces the existing secondary <select> with this new HTML.

      As I said, there are other ways, but they all involve reloading the page, which is inefficient and annoying for the user.

        The function then invokes the AJAX functions to retrieve a page on the server called itemselect.php, passing the selected category ID in the URL; this PHP script returns an HTML <select> control containing the items within the newly selected category. Finally, updateItems() replaces the existing secondary <select> with this new HTML.

        So itemselect.php should get the id, retrieve and echo the subcategories of the selected category?

          Correct. If you were to pull up, say, itemselect.php?category_id=5 in the browser, it would output something like this:

          <select name="item_id" id="itemselect">
              <option value="1">Item 1</option>
              <option value="2">Item 2</option>
              <option value="3">Item 3</option>
          </select>

          Of course, you won't be viewing this page directly in the browser; it's only accessed by the updateItems() function, to fetch the HTML to use for the secondary <select> box.

          I've probably made it sound more complicated than it really is. This page explains it in a little more detail; I stole my AJAX functions from them, and knocked together the updateItems() function myself.

          I'm sure it could be streamlined a bit, but it works like a charm.

          Let me know if you get it working!

            Excellent! It's working. That's a great script and i like the way it's working with no refresh. Thank you so much for your help mate!

            I've got one more question about this. Is it possible not to display the second menu when the category selected from the first one has no subcategories?

              Hi im looking to do the same sort of thing, and have been following your example. I have got the two list boxes to appear on the form, and the first one populates perfectly. When i select the value from the first list box, i need it to look up a second table. the value from the first list box is required for this, so i would need a sql statement something like this:

              SELECT TeamID, CountyID, Name FROM teams WHERE CountyID = '"value from first list box"

              how could i work this?

                create a new file called itemselect.php

                start this file with:
                $id = $_GET['category_id'];
                and then create your query using the $id . here's how my file looks like:

                <?php
                require_once ('includes/dbconnect.inc.php');
                $id = $_GET['category_id'];
                $query = @mysql_query ("SELECT sub.id, sub.name FROM sub, categorysub WHERE 
                						categorysub.categoryid='$id' AND categorysub.subid=sub.id");
                ?>
                    <select name="item_id" id="itemselect"> 
                <?
                        while ( $subcategory = mysql_fetch_array( $query ) ) { 
                            echo '<option value="' . $subcategory[0] . '">' . $subcategory[1] . '</option>';     
                } ?> </select>

                  see the require once line, is that just a file with your connection code in it? Would this be considered better practice than to have it on each page?

                    Still cant get it working. heres what i have

                    I have created a file which i just called ajax.php with the following code in it:

                    <?php
                    
                    define( "DB_HOST", "localhost" );
                    define( "DB_NAME", "gaa" );
                    define( "DB_USER", "" );
                    define( "DB_PASS", "" );
                    
                    $dbconn = mysql_connect( DB_HOST, DB_USER, DB_PASS );
                    mysql_select_db( DB_NAME, $dbconn );
                    
                    ?> 
                    
                    <html>
                    <head>
                    <title>Untitled Document</title>
                    
                    <script>
                    
                        function HttpRequest( url ) 
                    
                    	var pageRequest = false // variable to hold ajax object
                        if (!pageRequest && typeof XMLHttpRequest != 'undefined')
                           pageRequest = new XMLHttpRequest()
                    
                        if (pageRequest){ //if pageRequest is not false
                           pageRequest.open('GET', url, false); //get page synchronously
                           pageRequest.send(null);
                           return( embedpage(pageRequest) );
                           }
                        }
                    
                        function embedpage(request) {
                        //if viewing page offline or the document was successfully retrieved online (status code=2000)
                        if (window.location.href.indexOf("http")==-1 || request.status==200)
                           return(request.responseText);
                        }
                    
                        function updateItems() {
                            category_id = document.getElementById("categoryselect").value;
                            document.getElementById("itemselect").options[0] = new Option( "Loading...", null, true, true );
                            document.getElementById("itemselect").disabled = true;
                            // load new list
                            newselect = HttpRequest( "itemselect.php?category_id=" + category_id );
                            document.getElementById("itemselectdiv").innerHTML = newselect;
                        }
                    
                    </script> 
                    
                    </head>
                    
                    <body>
                    	<form>
                    
                    <select name="category_id" onchange="updateItems();" id="categoryselect">
                        <option selected="selected"></option>
                        <?php
                    
                        $categories = mysql_query( "SELECT CountyID, County FROM counties ORDER BY County" );
                    
                        while ( $category = mysql_fetch_array( $categories ) ) {
                            echo '<option value="' . $category["CountyID"] . '">' . $category["County"] . '</option>';    
                        }        
                    
                        ?>
                    </select>
                    
                    <div id="itemselectdiv">
                    <select name="item_id" id="itemselect">
                        <option></option>
                    </select>
                    </div>
                    
                    </form> 
                    </body>
                    </html>
                    
                    

                    Then i created the itemselect file with the code you suggested, except i changed the sql statement to suit my database:

                    <?php
                    	$username="";
                    	$password="";
                    	$database="gaa";
                    
                    mysql_connect(localhost,$username,$password);
                    @mysql_select_db($database) or die( "Unable to select database");
                    
                    $id = $_GET['category_id'];
                    $query = @mysql_query ("SELECT TeamID, CountyID, Name FROM teams WHERE CountyID='$id'");
                    ?>
                        <select name="item_id" id="itemselect">
                    <?
                            while ( $subcategory = mysql_fetch_array( $query ) ) {
                                echo '<option value="' . $subcategory[0] . '">' . $subcategory[1] . '</option>';     
                    } ?> </select>
                      aidanmcg33 wrote:

                      see the require once line, is that just a file with your connection code in it? Would this be considered better practice than to have it on each page?

                      you just don't need to copy all that code for each file

                        mikawhat wrote:

                        I've got one more question about this. Is it possible not to display the second menu when the category selected from the first one has no subcategories?

                        Sure. Just set up your itemselect.php file to produce no output for empty categories.

                        You'll have to make a slight adjustment to the Javascript updateItems() function, though - because the following lines assume that an HTML element with the ID "itemselect" will always be present, and that will no longer the case when an empty category is selected:

                        document.getElementById("itemselect").options[0] = new Option( "Loading...", null, true, true );
                        document.getElementById("itemselect").disabled = true;

                        Probably the easiest solution is to only execute this code if the "itemselect" element does, in fact, exist:

                        if ( document.getElementById("itemselect") ) {
                            document.getElementById("itemselect").options[0] = new Option( "Loading...", null, true, true );
                            document.getElementById("itemselect").disabled = true;
                        }

                        (I haven't tested this - but I think it'll work.)

                          aidanmcg33 wrote:

                          see the require once line, is that just a file with your connection code in it? Would this be considered better practice than to have it on each page?

                          Whenever you have code (PHP, HTML, Javascript, or anything else) that's used on more than one page, always use include files.

                          This makes it much, much, much easier to manage even smaller sites - because when you need to modify a function, or the HTML navigation bar, or whatever, you only have to change one file, instead of every page on the site. If you have a site with hundreds or thousands of pages, it's damn near impossible to manage without includes.

                          It also makes your code cleaner, more concise, and easier to read. So, yes, this is definitely considered good practice.

                          Wherever a file is included with require_once(), it'll be exactly as if the actual code in that file appeared in the same place as the call to require_once(). You can even nest includes.

                          The PHP functions include(), include_once(), and require() are slight variations on this functionality, but it's generally best to use require_once().

                          Always use include files. You'll love yourself for it.

                            it didn't work with the if statement. i have a thought about this but i need to know something. is there a way to get the value of category_id and use it as soon as it has been changed by selecting a category?

                            if ($subcategory > 0) { //if there's a sub category
                            echo  '<div id="itemselectdiv"> 
                                <select name="item_id" id="itemselect"> 
                                    <option></option> 
                                </select> 
                                </div>';
                            }

                            This is what i want to do, but i'll need the category_id in order to use it in a query and check if the category is empty. When the form is sent i can get it with $_POST['category_id'] but i want that value before the form is sent (if possible).

                              4 days later

                              THere's a small problem with this. When i make some changes to the subcategories the drop down menus will not display those changes unless i close the current window and open the page in a new window. is there a way to fix this problem?

                                Hi, I am trying to do the same thing but I got only 2 empty boxes.
                                What do I have to change in the function updateItems() to fit my tables?

                                Please advise. Thanks in advance.

                                  if you get two empty boxes you probably have a mistake in your query. With a correct query you should be able seeing at least the contents of the first box.

                                    I corrected a typo and got result in the first box but still nothing in the next. Any suggestion?
                                    I didn't touch the function updateitems() at all. Is there something I should change there or what ?

                                    My itemselect,php as follow:

                                    <?php
                                    $id = $_POST["CitySelect"];
                                    include("connectdb.php");
                                    $query=mysql_query("SELECT * FROM City, District WHERE District.CityID=City.CityID AND City.CityName='$id' ");
                                    if(!$query) die('An SQL error occurred: '.mysql_error());
                                    ?>
                                    <select name="item_id" id="itemselect">
                                    <?php
                                    while ($subcategory=mysql_fetch_array($query))
                                    {
                                    echo '<option value=" '.$subcategory["DistrictID"].' ">'.$subcategory["DistrictName"] . '</option>';

                                    }
                                    ?>
                                    </select>