
Good content takes time and effort to come up with.
Please consider supporting us by just disabling your AD BLOCKER and reloading this page again.
Hola Amigos! In this article, you will learn how to create a dependency dropdown with jQuery Ajax & PHP.
Code available in GitHub @ Dependency Dropdown
We will cover the following topics
To make you understand very easily let's start with an example which you might have seen at least once.
Example: Most of the time you might be loading
Or you might be having similar requirements in your project
The problem with the above is loading all the data at a time and passing to your HTML (ie Countries -> States -> Cities OR Device Category -> Company -> Models). If you select India as a country then you might need only Indian States & Cities no need to be bothered with other country States & Cities.
If the data is very huge then it will take some time to load the data and make your user experience very bad and some may never come back to your website.
You don't need States
& Cities
list till you select Country
. So when sending the data to the frontend just send a list of all the Countries
. When user selects Country then load that particular Countries
States
& when user the selects State
then load that particular State's
Cities
Let's start writing some code.
The following is the project structure that we will start working with.
Lets me explain what all we are keeping where
api
(Folder) - Keep all our API's
api/city_by_state.php
- API Get's list of all cities by state_id
api/state_by_country.php
- API Get's list of all states by country_id
assets
(Folder) - Keep all our CSS, JS, IMAGES
assets/css/style.css
- Simple style to center align the select dropdown
assets/js/cities_by_state.js
- On change of state dropdown send AJAX request to pull all cities
assets/js/states_by_country.js
- On change of country dropdown send AJAX request to pull all states
assets/js/jquery.js
- latest minified jQuery library. You can use CDN too
config.php
- Holds all your project configuration file
Country.php
(class) - Country class having methods to interact with Database
db.php
(PHP PDO Connection) - This is standard PHP PDO Connection
index.php
(Drop Down Demo) - This is the main file which I will demonstrate the dropdown functionality
Lets see our database structure now
demo
- Database name
countries
- Table to store all countries
states
- Table to store all states related to countries
cities
- Table to store all country and state-related cities
/** Create Datbase & Use it to dump tables and records */
CREATE DATABASE `demo`;
USE `demo`;
/** Cities tables */
CREATE TABLE `cities` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`country_id` int(11) unsigned NOT NULL,
`state_id` int(11) unsigned NOT NULL,
`name` varchar(100) NOT NULL DEFAULT '',
`code` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `cities` (`id`, `country_id`, `state_id`, `name`, `code`)
VALUES
(1,1,1,'Hubli',NULL),
(2,1,1,'Dharwad',NULL),
(3,1,2,'Chennai',NULL),
(4,1,2,'Madhurai',NULL);
/** Countries Table */
CREATE TABLE `countries` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`name` varchar(100) NOT NULL DEFAULT '',
`code` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `countries` (`id`, `name`, `code`)
VALUES
(1,'India','IN');
/** States Table */
CREATE TABLE `states` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`country_id` int(11) unsigned NOT NULL,
`name` varchar(100) NOT NULL DEFAULT '',
`code` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `country_id` (`country_id`),
CONSTRAINT `states_ibfk_1` FOREIGN KEY (`country_id`) REFERENCES `countries` (`id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `states` (`id`, `country_id`, `name`, `code`)
VALUES
(1,1,'Karnataka',NULL),
(2,1,'Tamilnadu',NULL);
<?php
$config = [
'base_url' => 'http://127.0.0.1/dependency_dropdowns',
'database' => [
'host' => 'localhost',
'db_name' => 'demo',
'db_username' => 'root',
'db_password' => 'root'
]
];
<?php
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL | E_STRICT);
require_once 'config.php';
$host = $config['database']['host'];
$db_name = $config['database']['db_name'];
$db_username = $config['database']['db_username'];
$db_password = $config['database']['db_password'];
$dsn = 'mysql:host=' . $host . ';dbname=' . $db_name;
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
PDO::ATTR_EMULATE_PREPARES => false,
];
try {
$pdo = new PDO($dsn, $db_username, $db_password);
} catch (PDOException $e) {
exit($e->getMessage());
}
Let's see the API implementation now so that at the later part we can completely focus on HTML design and Javascript AJAX request.
/** Required if not added then you may get CORS error in AJAX */
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Origin, Methods, Content-Type");
/** Necessary to let the other applications and software to know that your returning JSON data */
header('Content-Type: application/json; charset=UTF-8');
/** Only allow if POST request */
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
/** If you have any TOKEN or user validation you can do it here */
try {
/** Country validation */
$countryId = isset($_POST['country_id']) ? $_POST['country_id'] : '';
if (empty($countryId)) {
throw new Exception('Country field required');
}
/** Validate if country exists */
$countryStmt = $pdo->prepare("SELECT `id`, `name` FROM `countries` WHERE `id` = :country_id");
$countryStmt->execute([':country_id' => $countryId]);
$country = $countryStmt->fetchObject();
if (!$country) {
throw new Exception('Country not found');
}
/** Code to fetch list of states by country_id */
$stateStmt = $pdo->prepare("SELECT `id`, `name` FROM `states` WHERE `country_id` = :country_id");
$stateStmt->execute([':country_id' => $countryId]);
$states = $stateStmt->fetchAll(PDO::FETCH_OBJ);
/** Return 200 status code with other json data */
http_response_code(200);
echo json_encode([
'status' => 'success',
'message' => 'Successfully fetch details',
'data' => [
'country' => $country,
'states' => $states
]
]);
exit;
} catch (Exception $e) {
/** Return 400 status code if any error thrown */
http_response_code(400);
echo json_encode([
'status' => 'error',
'message' => 'Error in fetching state details',
'error' => $e->getMessage()
]);
exit;
}
}
/** If GET request to the API then return 405 (Method Not Supported) status code */
http_response_code(405);
echo json_encode([
'status' => 'error',
'message' => 'Method not supported',
]);
exit;
The complete code of the file will look like the following
<?php
require_once '../db.php';
/** Required if not added then you may get CORS error in AJAX */
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Methods: POST");
header("Access-Control-Allow-Headers: Origin, Methods, Content-Type");
/** Necessary to let the other applications and software to know that your returning JSON data */
header('Content-Type: application/json; charset=UTF-8');
/** Only allow if POST request */
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
/** If you have any TOKEN or user validation you can do it here */
try {
/** Country validation */
$countryId = isset($_POST['country_id']) ? $_POST['country_id'] : '';
if (empty($countryId)) {
throw new Exception('Country field required');
}
/** Validate if country exists */
$countryStmt = $pdo->prepare("SELECT `id`, `name` FROM `countries` WHERE `id` = :country_id");
$countryStmt->execute([':country_id' => $countryId]);
$country = $countryStmt->fetchObject();
if (!$country) {
throw new Exception('Country not found');
}
/** Code to fetch list of states by country_id */
$stateStmt = $pdo->prepare("SELECT `id`, `name` FROM `states` WHERE `country_id` = :country_id");
$stateStmt->execute([':country_id' => $countryId]);
$states = $stateStmt->fetchAll(PDO::FETCH_OBJ);
/** Return 200 status code with other json data */
http_response_code(200);
echo json_encode([
'status' => 'success',
'message' => 'Successfully fetch details',
'data' => [
'country' => $country,
'states' => $states
]
]);
exit;
} catch (Exception $e) {
/** Return 400 status code if any error thrown */
http_response_code(400);
echo json_encode([
'status' => 'error',
'message' => 'Error in fetching state details',
'error' => $e->getMessage()
]);
exit;
}
}
/** If GET request to the API then return 405 (Method Not Supported) status code */
http_response_code(405);
echo json_encode([
'status' => 'error',
'message' => 'Method not supported',
]);
exit;
This is how our frontend looks like
Following is the code to get the above frontend view. I have included external CSS make sure to include it. Most of the code explanation will be done in code so that you can understand very easily.
<?php
/** Get list of all countries */
require_once './Country.php';
/** Load the dropdown with countries */
$countries = (new Country)->getAllCountries();
?>
<!DOCTYPE html>
<html lang="en">
<head>
<title>Dependency Dropdown Demo</title>
<link rel="stylesheet" href="./assets/css/style.css">
</head>
<body>
<div class="container">
<h3 class="text-center">Dependency Dropdown Demo</h3>
<div class="dropdown">
<div><label for="country">Country <small class="country-status"></small></label></div>
<div>
<select name="country" id="country">
<option value="">Select Country</option>
<?php
/** We get list of all the countries from the above PHP query
* If you need you can even trigger on page load
*/
foreach ($countries as $country) {
?>
<option value="<?php echo $country->id; ?>"><?php echo $country->name; ?></option>
<?php
}
?>
</select>
</div>
</div>
<div class="dropdown">
<div><label for="state">State <small class="state-status"></small></label></div>
<div>
<!-- On page load we wont be using states,
as we will load it after selecting country -->
<select name="state" id="state">
</select>
</div>
</div>
<div class="dropdown">
<div><label for="city">City <small class="city-status"></small></label></div>
<div>
<!-- On page load we wont be using cities too,
as we will load it after selecting state -->
<select name="city" id="city">
</select>
</div>
</div>
</div>
<!-- Javascript Files -->
<script src="./assets/js/jquery.js"></script>
<script src="./assets/js/states_by_country.js"></script>
<script src="./assets/js/cities_by_state.js"></script>
</body>
</html>
Ya, that's it for the frontend for the view. I will cover the AJAX part in the next section.
On change of the Country select the dropdown I want to load the States, this can be achieved with Javascript AJAX request.
Writing AJAX request with plain Javascript can be tricky, so we will be using jQuery AJAX request. Feel free to use AXIOS too :)
The following code is triggered when you change the Country dropdown
/** On change of Country dropdown trigger the following code */
$('#country').on('change', function() {
/** Variable to hold countryId */
var countryId = $(this).val();
/** Variable to hold countryStatus */
var countryStatus = $('.country-status');
/** Validate country */
if (countryId == 'undefined' || countryId == '') {
countryStatus.html('Please select country');
return false;
}
countryStatus.html('');
/** Load the states based on the country selected using AJAX call */
getStatesByCountryId(countryId);
});
getStatesByCountryId
)The following code will be called from the above select dropdown on the change trigger.
/** Function to implement the AJAX states fetching */
function getStatesByCountryId(countryId) {
var countryStatus = $('.country-status');
countryStatus.html('Loading states...');
/** AJAX Request to API to fetch states */
$.ajax({
"url": "api/state_by_country.php",
"type": "POST",
"dataType": "JSON",
"data": {
country_id: countryId
},
"success": function(retObj) {
/** Check if the ajax request return data had any error */
if (retObj.status == 'error') {
countryStatus.html(retObj.error);
return false;
}
/** If the ajax request return data was success */
/** Variable to store the states records */
var states = retObj.data.states;
var stateOptions = '<option value="">Select State</option>';
/** Loop through states and append to state select dropdown */
$.each(states, function(key, state) {
stateOptions += "<option value='" + state.id + "'>" + state.name + "</option>"
});
$('#state').html(stateOptions);
countryStatus.html('');
}
});
}
state_by_country.js
Complete CodeThe complete code for the JS will look like the following
/** On change of Country dropdown trigger the following code */
$('#country').on('change', function() {
/** Variable to hold countryId */
var countryId = $(this).val();
/** Variable to hold countryStatus */
var countryStatus = $('.country-status');
/** Validate country */
if (countryId == 'undefined' || countryId == '') {
countryStatus.html('Please select country');
return false;
}
countryStatus.html('');
/** Load the states based on the country selected using AJAX call */
getStatesByCountryId(countryId);
});
/** Function to implement the AJAX states fetching */
function getStatesByCountryId(countryId) {
var countryStatus = $('.country-status');
countryStatus.html('Loading states...');
/** AJAX Request to API to fetch states */
$.ajax({
"url": "api/state_by_country.php",
"type": "POST",
"dataType": "JSON",
"data": {
country_id: countryId
},
"success": function(retObj) {
/** Check if the ajax request return data had any error */
if (retObj.status == 'error') {
countryStatus.html(retObj.error);
return false;
}
/** If the ajax request return data was success */
/** Variable to store the states records */
var states = retObj.data.states;
var stateOptions = '<option value="">Select State</option>';
/** Loop through states and append to state select dropdown */
$.each(states, function(key, state) {
stateOptions += "<option value='" + state.id + "'>" + state.name + "</option>"
});
$('#state').html(stateOptions);
countryStatus.html('');
}
});
}
Now you can run the above project in your browser with the following URL
http://localhost/dependency_dropdowns/
Don't panic if you do not see the remaining code I have added in GitHub.
Hope this was helpful. Kindly share with your friends :)
Code available in GitHub @ Dependency Dropdown
Why namespace And use Keywords Used In PHP
Upload File From Frontend Server {GuzzleHttp} To REST API Server In PHP {Laravel}
Sass or SCSS @mixin vs @extends vs Placeholder (%)
Push Files To CPanel / Remote Server using FTP Software FileZilla
Lazy Load YouTube And Other Videos In Website
SQLite Doesn't Support Dropping Foreign Keys in Laravel
Factories To Speed Up Test-Driven Development In Laravel
Send SMS With Amazon SNS (Simple Notification Service) Using PHP
Install NGINX In Linux / Ubuntu And Managing
Facebook Login With PHP Laravel Socialite
Lazy Load Images In Chrome With This Simple Trick
Generate Sitemap in PHP Laravel
Detect AdBlocker With Javascript And Increase Website Ads Revenue