Extjs Cascading (Dependent) Combo Boxes

This tutorial was written after one of my readers requested help with creating a dependent dropdown menu for continents, countries and states. I hope this helps everyone out there, who like myself, have struggled with this in the past.

First you’ll need to create the connect.php file, explained here.

Next create the 3 mysql/php/json files used for:
1. gathering data from mysql,
2. storing the data into a json array for each of the combo boxes you’ll be using (Continent, Country and State).

(Please adjust the paths to connect.php (mentioned above) and all other files used in this example
accordingly and create the required tables in mysql as needed)

Start by creating the continentQ.php file, to gather the continent data:

continentQ.php

<?php

// Begin continentQ.php

include('../../Connections/connect.php');

//connection String
$con = mysql_connect($hostname, $username, $password) or die('Could not connect: ' . mysql_error());
//select database
mysql_select_db($database, $con);
//Select The database
$bool = mysql_select_db($database, $con);
if ($bool === False){
	print "can't find $database";
}


$query = "SELECT continentid, continent FROM tblcontinents ORDER by continent ASC";

$result = mysql_query($query, $con); 

// Test the query
if(!$result){
    $res = array('success' => false, 'error' => 'Whatever error message you want to display here.');
	echo json_encode($res);
    exit();
}


while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
	$myContinents[] = array(
        'cid' => $row['continentid'],
        'continent' => $row['continent']
		);
}


$myData = array('success' => true, 'myContinents' => $myContinents);

echo json_encode($myData);

// End continentQ.php
?>

Now create the file to load the data for the Countries, we’ll call this countryQ.php.

countryQ.php


<?php

// Begin countryQ.php

include('../../Connections/connect.php');

//connection String
$con = mysql_connect($hostname, $username, $password) or die('Could not connect: ' . mysql_error());
//select database
mysql_select_db($database, $con);
//Select The database
$bool = mysql_select_db($database, $con);
if ($bool === False){
	print "can't find $database";
}


$cid = $_POST['cid']; // This is sent to us from the continent drop down via the ajax request, after the user selects a continent

$query = "SELECT continentid, countryid, country FROM tblcountry WHERE (continentid LIKE '$cid')ORDER by country ASC";

$result = mysql_query($query, $con); 

// Test the query
if(!$result){
    $res = array('success' => false, 'error' => 'Whatever error message you want to display here.');
	echo json_encode($res);
    exit();
}


while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
	$myCountries[] = array(
        'countryid' => $row['countryid'],
        'country' => $row['country']
		);
}


$myData = array('success' => true, 'myCountries' => $myContinents);

echo json_encode($myData);

// End countryQ.php
?>

And lastly, create the file to populate the State dropdown, we’ll call it stateQ.php.

stateQ.php

<?php

// Begin stateQ.php

include('../../Connections/connect.php');

//connection String
$con = mysql_connect($hostname, $username, $password) or die('Could not connect: ' . mysql_error());
//select database
mysql_select_db($database, $con);
//Select The database
$bool = mysql_select_db($database, $con);
if ($bool === False){
	print "can't find $database";
}


$country = $_POST['countryid']; // This is sent to us from the continent drop down via the ajax request, after the user selects a continent

$query = "SELECT countryid, stateid, state FROM tblstate WHERE (countryid LIKE '$country')ORDER by state ASC";

$result = mysql_query($query, $con); 

// Test the query
if(!$result){
    $res = array('success' => false, 'error' => 'Whatever error message you want to display here.');
	echo json_encode($res);
    exit();
}


while ($row = mysql_fetch_array($result, MYSQL_ASSOC)) {
	$myStates[] = array(
        'stateid' => $row['stateid'],
        'state' => $row['state']
		);
}


$myData = array('success' => true, 'myStates' => $myContinents);

echo json_encode($myData);

// End stateQ.php
?>

Now that you have the 3 files to gather the data and create the json stores, we need a file to create the datastores we’ll use for each dropdown, we’ll call this file datastores.js (We assume the 3 files above and the datastore.js are in the same location, please adjust accordingly).

datastores.js

/* Begin datastore.js */

//Define the application Namespace
Ext.ns('App', 'App.worlddata');

Ext.onReady(function(){


App.worlddata.continent_store = new Ext.data.Store({
        reader: new Ext.data.JsonReader({
        		fields : ['continentid','continent'],
          		root: 'myContinents'
        						}),
  		proxy: new Ext.data.HttpProxy({
            url: 'continentQ.php'
        }),
        remoteSort: true,
        autoLoad: true
    });

App.worlddata.country_store = new Ext.data.Store({
        reader: new Ext.data.JsonReader({
        		fields : ['countryid','country'],
          		root: 'myCountries'
        						}),
  		proxy: new Ext.data.HttpProxy({
            url: 'countryQ.php'
        }),
        remoteSort: true
    });
    
    
App.worlddata.state_store = new Ext.data.Store({
        reader: new Ext.data.JsonReader({
        		fields : ['stateid','state'],
          		root: 'myStates'
        						}),
  		proxy: new Ext.data.HttpProxy({
            url: 'stateQ.php'
        }),
        remoteSort: true
    });    


}); // end extonready

/* End datastore.js */

Now we create the ext file that’ll contain the 3 dropdowns, please adjust accordingly, I won’t be showing how to create an entire form here, just how to create the 3 dropdowns and add them to a simple form, we’ll call this worldapp.js.

worldapp.js

/*  Begin ext file that contains our app, worldapp.js */
Ext.ns('App', 'App.worlddata');

Ext.onReady(function(){

continent_cmb = new Ext.form.ComboBox({store: App.worlddata.continent_store,
			            id:'cont_id',
			            name: 'cont_txt',
			            dataIndex: 'continent',
			            hiddenName:'continent_hid',
			            valueField:'continentid',
			            displayField:'continent',
			            width: 55,
			            typeAhead: true,
			            mode: 'local',
			            forceSelection: true,
			            triggerAction: 'all',
			            selectOnFocus:true,
			            allowBlank: false,
			            listeners: {
									select:  
						// 
									function(e) {
						// First find out what continent has been selected			
									var cont = Ext.getCmp('cont_id').getValue();
							
									var country = Ext.getCmp('country_id');
									var state = Ext.getCmp('state_id');
									
									// We need to clear the datastore and fields in case the user chose a different continent
									country.store.removeAll();		
									state.store.removeAll();	
									
																		
									// Now reload the store for the countries with the param above
									country.store.reload({params: {cid: cont}});
									
									}
			            }
	})
       
       
	 country_cmb = new Ext.form.ComboBox({store: App.worlddata.country_store,
		            id:'country_id',
		            hiddenName:'country_hid',
		            valueField:'country_id',
		            displayField:'country',
		            width: 55,
		            typeAhead: true,
		            mode: 'local',
		            forceSelection: true,
		            triggerAction: 'all',
		            lastQuery: '',
		            selectOnFocus:true,
		            allowBlank: false,
		            listeners: {
								select:  
					// 
								function() {
					// Find out what country has been selected			
								var country_val = Ext.getCmp('country_id').getValue();
								
						
								var state = Ext.getCmp('state_id');
								
								// Clear the state dropdown in case a different country has been selected
								state.store.removeAll();
					
								// Load the store so the state dropdown is populated again with new data		
							    	state.store.reload({params: {countryid: country_val}});
								
							    
								
								}
		            }
		            })  
	            
	            
	            
	state_cmb = new Ext.form.ComboBox({store: App.worlddata.state_store,
	            id:'state_id',
	            hiddenName:'state_hid',
	            valueField:'stateid',
	            displayField:'state',
	            width: 35,
	            typeAhead: true,
                    mode: 'local',
	            forceSelection: true,
	            allowBlank: false,
	            triggerAction: 'all',
	            lastQuery: '',
	            selectOnFocus:true
       })	            




sampleform = new Ext.FormPanel({ 
        labelWidth:80,
        frame:true, 
        title:'World App', 
        defaultType:'textfield',
	items:[continent_cmb, country_cmb, state_cmb] 
            
           });


  win = new Ext.Window({
        layout:'fit',
        width:300,
        height:150,
        closable: false,
        resizable: false,
        plain: true,
        border: false,
        items: [sampleform]
	});
	
	
	
  win.show();


}); // End of ext file

/* end of file worldapp.js */

Here’s the index.php file, again, adjust the paths accordingly, this will be the file you’ll add to the root of your app, when you go to i.e. http://localhost/

index.php

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html>

	<head>

	

	</head>

	<body></body>

	

	<link rel="stylesheet" type="text/css" href="../javascript/ext-3.3.0/resources/css/ext-all.css"/>

    	<script type="text/javascript" src="../javascript/ext-3.3.0/adapter/ext/ext-base.js"></script>

    	<script type="text/javascript" src="../javascript/ext-3.3.0/ext-all.js"></script>

    	<script type="text/javascript" src="datastores.js"></script>

	<script type="text/javascript" src="worldapp.js"></script>	

	

</html>

These are all the files you’ll need for your app, please remember to adjust paths, adjust queries and add/remove items as needed. I hope this step by step tutorial has helped you some. Thank you for stopping by and please share with others, after all, code should be free.foscode.com | because code should be free

13 thoughts on “Extjs Cascading (Dependent) Combo Boxes

  1. Thanks Dear…Now i m going to develop an ERP web based Intranet for compny using Extjs CI PHP and Mysql…
    if u have any application for sample kindly teach how to work or integrate ExtJs with CI.

    samir

  2. @Samir, I’ll be be glad to help you out, I always post new tutorials and if you see something that hasn’t yet been posted just let me know and I’ll try to get something put together on the site for everyone. Most of the posts on my site were taken from applications I have built myself, so hopefully they can guide you in the right direction. Thanks for stopping by.

  3. Pingback: Open iReport jrxml from ExtJs as pdf | foscode

  4. Hi Dan this is samir once again i want your help in my application i use extjs php mysql . and that is i create a menu and help need: how to load a grid click on menu item.

  5. @Samir Hi Samir, nice to have you back. To load a grid after clicking a menu button, or any other type of field (texttfield, combobox …) all you need to do is create a listener and reload the grid store with the combo/textfield value as one of the parameters. So let’s say you have a combo box, create a listener as such:

    listeners: {
    onSelect : function() {

    comboboxvalue = Ext.getCmp(‘combobox_id’).getValue(); // The value from the combobox

    // Now reload the grid store with the value from the combobox as a parameter

    gridstore.reload({
    params: {
    someparameter: comboboxvalue
    }
    });

    }
    }

    Hope this helps, please let me know if it doesn’t make sense. You will also need to adjust the php file that loads the grid store, so the parameter you are sending is used by the query when loading the store.

  6. Hello Dan thank you for this useful tutorial.

    BTW I think that on line 40 of datastore.js there should be:

    App.worlddata.continent_store.load();

    Otherwise the first combo “Continent” cannot starts with correct continent names.

  7. @Riccardo Thanks for stopping by, I’m glad the tutorial was helpful to you. Also, thanks for bringing that up, I’ve missed the line on datastore.js above so the store will auto load. I’ve corrected it, so now the continent store will auto load since it has the option autoLoad: true (line 17 on datastore.js file). Thanks again.

  8. Hi Dan!!! Thanks for your tutorial!!! I have one question!… when I selected a continent, then a country a then a state, if i select other country in the state combo box still there the state that i selected before.

    How to clear the combobox text?!

    Thenks!
    eliss

  9. @elis Thanks for stopping by and the kind comments. Just change the listener from select to change, so the dependent dropdown is cleared on change event instead of select; OR add this to the select listener on the country combo; OR create a separate change listener to include something like this:
    Ext.getCmp(‘state_id’).setValue(”);

  10. This is an easy to use code to select records from MySQL database table and display in dropdown combo box using PHP.

    $cn=mysql_connect($db_host,$db_user,$db_password) or die(mysql_error());
    mysql_select_db($db_name,$cn) or die(mysql_error());
    $sql = “SELECT field_name FROM table_name”;
    $rs = mysql_query($sql) or die(mysql_error());
    echo “”;
    while($row = mysql_fetch_array($rs)){
    echo “”.$row["field_name"].”";
    }mysql_free_result($rs);
    echo “”;

  11. Thanks for your post,

    its really useful, i did it with RoR.

    Thanks
    Naveen Kumar Madipally

  12. Hello,
    this is a wonderful tutorial, I feel it, but I have one problem after setting up the database and all the files and connections. When I click on the Continent Combo everythings alright, I get the continents. But when I click on the countries´ combo it´s empty and i get the response from countryQ.php

    {“success”:true,”myCountries”:null}

    I checked the names of my tables and the columns, but what can be wrong? I don´t find my fault. Any idea?

    Thank you.
    Chris

  13. Thank you very much for posting this tutorial. It helps me to solve bug. once again thank you.

Leave a Reply

Your email address will not be published. Required fields are marked *

*


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>