jQuery Dependent DropDown List – Countries and States

Last modified on August 22nd, 2019 by Vincy.

Adding Dependent dropdowns will be a very useful feature when there is a dependency between the options of the dropdown fields.

For example, if we need to list out the posts based on its category then we can have dependent category-post dropdowns.

View Demo

What is inside?

  1. About this example
  2. File structure
  3. HTML form with dependent dropdown
  4. How to get country’s states using jQuery AJAX
  5. PHP code to read country-state from database
  6. Database script
  7. jQuery dependent dropdown example output

About this example

In this tutorial, we are going to create country-state dependent dropdowns. On changing the countries dropdown values, the state dropdown options is loaded dynamically.

I use jQuery AJAX to get the dependent options for the state dropdown based on the selected country.

In a previous tutorial, we have seen an example with the countries list to filter country name using jQuery autocomplete.

File structure

jQuery Dependent Dropdown Example Files

HTML form with dependent dropdown

The following HTML code contains dependent dropdowns for countries and states. Country options are read from the database and shown in the dropdown on page load.

Initially, the state dropdown has no options. On changing the country dropdown values, a jQuery function is called to get dependent state options and loaded dynamically.

<html>
<head>
<TITLE>jQuery Dependent DropDown List - Countries and States</TITLE>
<head>
<link href="./css/style.css" rel="stylesheet" type="text/css" />
</head>
<body>
    <div class="frmDronpDown">
        <div class="row">
            <label>Country:</label><br /> <select name="country"
                id="country-list" class="demoInputBox"
                onChange="getState(this.value);">
                <option value="">Select Country</option>
<?php
foreach ($countryResult as $country) {
    ?>
<option value="<?php echo $country["id"]; ?>"><?php echo $country["country_name"]; ?></option>
<?php
}
?>
</select>
        </div>
        <div class="row">
            <label>State:</label><br /> <select name="state"
                id="state-list" class="demoInputBox">
                <option value="">Select State</option>
            </select> <img id="loader" src="./images/loader.gif" />
        </div>
    </div>
</body>
</html>

How to get country’s states using jQuery AJAX

The following jQuery script shows a function to send an AJAX request to PHP to read state list depends on the selected country.

This AJAX call is set with the selected country id.

<script src="./vendor/jquery/jquery-3.2.1.min.js" type="text/javascript"></script>
<script>
function getState(val) {
    $("#loader").show();
	$.ajax({
	type: "POST",
	url: "./ajax-endpoint/get-state.php",
	data:'country_id='+val,
	success: function(data){
		$("#state-list").html(data);
		$("#loader").show();
	}
	});
}
</script>

PHP code to read country-state from database

In PHP, it connects the database to retrieve “states” table values based on the country id passed by jQuery AJAX call.

It forms state dropdown options and returns as the AJAX response. This response is inserted to the state dropdown.

<?php
namespace Phppot;

use \Phppot\DataSource;
require_once __DIR__ . './DataSource.php';
$ds = new DataSource();
$query = "SELECT * FROM country";
$countryResult = $ds->select($query);
?>
<?php
namespace Phppot;

use \Phppot\DataSource;
require_once __DIR__ . './../DataSource.php';
$ds = new DataSource();
if (! empty($_POST["country_id"])) {
    $query = "SELECT * FROM states WHERE countryID = ?";
    $paramType = 'd';
    $paramArray = array(
        $_POST["country_id"]
    );
    $StateResult = $ds->select($query, $paramType, $paramArray);
    ?>
<option value="">Select State</option>
<?php
    foreach ($StateResult as $state) {
        ?>
<option value="<?php echo $state["id"]; ?>"><?php echo $state["name"]; ?></option>
<?php
    }
}
?>

DataSource.php

<?php
namespace Phppot;

/**
 * Generic datasource class for handling DB operations.
 * Uses MySqli and PreparedStatements.
 *
 * @version 2.3
 */
class DataSource
{

    // PHP 7.1.0 visibility modifiers are allowed for class constants.
    // when using above 7.1.0, declare the below constants as private
    const HOST = 'localhost';

    const USERNAME = 'root';

    const PASSWORD = '';

    const DATABASENAME = 'phpsamples';

    private $conn;

    /**
     * PHP implicitly takes care of cleanup for default connection types.
     * So no need to worry about closing the connection.
     *
     * Singletons not required in PHP as there is no
     * concept of shared memory.
     * Every object lives only for a request.
     *
     * Keeping things simple and that works!
     */
    function __construct()
    {
        $this->conn = $this->getConnection();
    }

    /**
     * If connection object is needed use this method and get access to it.
     * Otherwise, use the below methods for insert / update / etc.
     *
     * @return \mysqli
     */
    public function getConnection()
    {
        $conn = new \mysqli(self::HOST, self::USERNAME, self::PASSWORD, self::DATABASENAME);
        
        if (mysqli_connect_errno()) {
            trigger_error("Problem with connecting to database.");
        }
        
        $conn->set_charset("utf8");
        return $conn;
    }

    /**
     * To get database results
     * @param string $query
     * @param string $paramType
     * @param array $paramArray
     * @return array
     */
    public function select($query, $paramType="", $paramArray=array())
    {
        $stmt = $this->conn->prepare($query);
        
        if(!empty($paramType) && !empty($paramArray)) {
            $this->bindQueryParams($stmt, $paramType, $paramArray);
        }
        
        $stmt->execute();
        $result = $stmt->get_result();
        
        if ($result->num_rows > 0) {
            while ($row = $result->fetch_assoc()) {
                $resultset[] = $row;
            }
        }
        
        if (! empty($resultset)) {
            return $resultset;
        }
    }
    
    /**
     * To insert
     * @param string $query
     * @param string $paramType
     * @param array $paramArray
     * @return int
     */
    public function insert($query, $paramType, $paramArray)
    {
        print $query;
        $stmt = $this->conn->prepare($query);
        $this->bindQueryParams($stmt, $paramType, $paramArray);
        $stmt->execute();
        $insertId = $stmt->insert_id;
        return $insertId;
    }
    
    /**
     * To execute query
     * @param string $query
     * @param string $paramType
     * @param array $paramArray
     */
    public function execute($query, $paramType="", $paramArray=array())
    {
        $stmt = $this->conn->prepare($query);
        
        if(!empty($paramType) && !empty($paramArray)) {
            $this->bindQueryParams($stmt, $paramType="", $paramArray=array());
        }
        $stmt->execute();
    }
    
    /**
     * 1. Prepares parameter binding
     * 2. Bind prameters to the sql statement
     * @param string $stmt
     * @param string $paramType
     * @param array $paramArray
     */
    public function bindQueryParams($stmt, $paramType, $paramArray=array())
    {
        $paramValueReference[] = & $paramType;
        for ($i = 0; $i < count($paramArray); $i ++) {
            $paramValueReference[] = & $paramArray[$i];
        }
        call_user_func_array(array(
            $stmt,
            'bind_param'
        ), $paramValueReference);
    }
    
    /**
     * To get database results
     * @param string $query
     * @param string $paramType
     * @param array $paramArray
     * @return array
     */
    public function numRows($query, $paramType="", $paramArray=array())
    {
        $stmt = $this->conn->prepare($query);
        
        if(!empty($paramType) && !empty($paramArray)) {
            $this->bindQueryParams($stmt, $paramType, $paramArray);
        }
        
        $stmt->execute();
        $stmt->store_result();
        $recordCount = $stmt->num_rows;
        return $recordCount;
    }
}

Database script

--
-- Table structure for table `country`
--

CREATE TABLE IF NOT EXISTS `country` (
`id` int(11) NOT NULL,
  `country_name` varchar(255) NOT NULL
);

INSERT INTO `country` (`id`, `country_name`) VALUES
(1, 'Brazil'),
(2, 'China'),
(3, 'France'),
(4, 'India'),
(5, 'USA');

--
-- Table structure for table `states`
--

CREATE TABLE IF NOT EXISTS `states` (
`id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `countryID` int(11) NOT NULL
);

INSERT INTO `states` (`id`, `name`, `countryID`) VALUES
(1, 'Sao Paulo', 1),
(2, 'Rio de Janeiro', 1),
(3, 'Ceara', 1),
(4, 'Santa Catarina', 1),
(5, 'Espirito Santo', 1),
(6, 'Beijing', 2),
(7, 'Hebei', 2),
(8, 'Jiangsu', 2),
(9, 'Guangdong', 2),
(10, 'Guangdong', 2),
(11, 'Ile-de-France', 3),
(12, 'Midi-Pyrenees', 3),
(13, 'Picardie', 3),
(14, 'Franche-Comte', 3),
(15, 'Alsace', 3),
(16, 'Haryana', 4),
(17, 'Andhra Pradesh', 4),
(18, 'Delhi', 4),
(19, 'Tamil Nadu', 4),
(20, 'Uttar Pradesh', 4),
(21, 'California', 5),
(22, 'Iowa', 5),
(23, 'New York4', 5),
(24, 'New Jersey', 5),
(25, 'Massachusetts', 5);

jQuery dependent dropdown – country and state – output

jQuery Dependent Dropdown Country-State Output

View DemoDownload

↑ Back to Top

Share this Article