I'm trying to connect 2 drop-downs so in the first I show a list of countries and based on the selection of the country I show a list of the cities for the country selected.
I have my index.php file which load all the countries correctly as seen in this image:
Code to load my countries
<select name="country" id="country">
<?php
$db = pg_connect("$db_host $db_name $db_username $db_password");
$query = "SELECT country FROM countries";
$result = pg_query($query);
if (!$result) {
echo "Problem with query " . $query . "<br/>";
echo pg_last_error();
exit();
}
printf ("<option value=Select>Select a Country</option>");
while($myrow = pg_fetch_assoc($result)) {
printf ("<option value=$myrow[country]>$myrow[country]</option>");
}
?>
</select>
Now I'm trying to do the same based on the selection from the previous "Select" but it is not working. The issue I'm having is getting the value selected in the country select because if I hard-type a value of a country like: $query = "SELECT city FROM cities where country = Albania"; then it works. Also I tried to print the value of the country selected: (echo $selectedCountry;) and it not printing anything so I'm guessing neither $selectedCountry = $_GET['country']; or $selectedCountry = $_POST['country']; are getting the value of the country selected.
<select name="city" id="city">
<?php
$db = pg_connect("$db_host $db_name $db_username $db_password");
$selectedCountry = $_GET['country'];
$selectedCountry = $_POST['country'];
echo $selectedCountry;
$query = "SELECT city FROM cities where country = ' $selectedCountry '";
$result = pg_query($query);
if (!$result) {
echo "Problem with query " . $query . "<br/>";
echo pg_last_error();
exit();
}
printf ("<option value=Select>Select a City</option>");
while($myrow = pg_fetch_assoc($result)) {
printf ("<option value=$myrow[city]>$myrow[city]</option>");
}
?>
</select>
Thank you very much in advance
UPDATE
This is what I see in the first Load. Where the country Select is loaded with all the values as per the image above and the city Select is empty (Only the "Select a city" value) waiting to be loaded with the values depending on the country selection.
LAST UPDATE - From Borna Suggestion
Borna,
I've tried your suggestion, below the exact code that I'm using. Using two countries as example. However, the cities are empty the first load and when I select a country nothing loads in the city Select and I get the following screen. It seams that it is actually not calling/running the getCities.php:
Index.html
<!DOCTYPE html>
<html>
<head>
<script>
function populateCities(citiesSelectBoxOptions){
document.getElementById("city").innerHTML = citiesSelectBoxOptions;
}
function httpGetAsync(theUrl, callback)
{
alert(theUrl);
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(xmlHttp.responseText);
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
</script>
</head>
<body>
<select name="country" id="country" onchange="httpGetAsync('http://localhost/FillCity/getCities?country=' + this.value, populateCities)">
<option value="Angola">Angola</option>
<option value="Spain">Spain</option>
</select>
<select name="city" id="city">
</select>
</body>
</html>
getCities.php
<?php
include("config.php");
$db = pg_connect("$db_host $db_name $db_username $db_password");
$selectedCountry = $_GET['country'];
echo "country: " .$country;
$query = "SELECT city FROM cities where country = ' $selectedCountry '";
$result = pg_query($query);
if (!$result) {
echo "Problem with query " . $query . "<br/>";
echo pg_last_error();
exit();
}
printf ("<option value='Select'>Select a City</option>");
while($myrow = pg_fetch_assoc($result)) {
printf ("<option value='$myrow[city]'>$myrow[city]</option>");
}
?>
UPDATE
If I run http://localhost/FillCity/getCities?country=Spain this is what I get
If I run just http://localhost/FillCity/getCities.php I get: (I'm getting the word country because I place and echo $country in the code to see the country selected)
This is my FillCity folder under my localhost (var/www/html)
And here is what I see when running the Index.html for the first time with Angola as default country.
If I select any country, Spain, as example this is what I get
LAST UPDATE
When I open the .html file and I select a country this is what I get (Still printing out that message on the screen):
Once I click Ok then it works and I can see all the cities for the country (But of course I would like not to have that message popping up)
Thanks again
Well, what you really need is AJAX call which allows you to communicate with server without reloading a page. All you have to do is basically send a new HTTP request with a country parameter to get the list of cities in it. The correct way would be to send (HTTP response) only the data(cities) in JSON or similar format, and not its presentation also (html), but for simplicity, you can continue to work like you started (return data with html).
Start by separating the code that generates HTML selectBoxOptions of cities in another script.
You will use that script to get the list of cities in particular country by using AJAX (XMLHttpRequest library).
Have a look at this, it's a working solution of your problem. HTTP request is sent whenever user changes the countrySelectBox option, that way your cities select box gets updated every time it needs.
All you have to do is change the url in the onchange attribute that points to your script (I previously said that you should move 2nd block of code into separate script).
<!DOCTYPE html>
<html>
<head>
<script>
function populateCities(citiesSelectBoxOptions){
document.getElementById("city").innerHTML = citiesSelectBoxOptions;
}
function httpGetAsync(theUrl, callback)
{
alert(theUrl);
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(xmlHttp.responseText);
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
</script>
</head>
<body>
<select name="country" id="country" onchange="httpGetAsync('www.yourdomain.com/getCities.php?country=' + this.options[this.selectedIndex].value, populateCities)">
<option value="Country1">Country 1</option>
<option value="Country2">Country 2</option>
</select>
<select name="city" id="city">
</select>
</body>
</html>
getCities.php
<?php
$db = pg_connect("$db_host $db_name $db_username $db_password");
$selectedCountry = $_GET['country'];
$query = "SELECT city FROM cities where country = ' $selectedCountry '";
$result = pg_query($query);
if (!$result) {
echo "Problem with query " . $query . "<br/>";
echo pg_last_error();
exit();
}
printf ("<option value='Select'>Select a City</option>");
while($myrow = pg_fetch_assoc($result)) {
printf ("<option value='$myrow[city]'>$myrow[city]</option>");
}
?>
EDIT:
httpGetAsync is native (only pure/vanilla javascript is used. No other libraries are used) javascript function that enables you to send HTTP request without reloading a page. I see you are using jQuery, which hides this function's complexity, same as form->submit, but I recommend you to learn how httpGetAsync works, because using a jQuery for such a simple task is overkill.
You don't need this javascript function
function getCity(countryId)
Instead, you should put your code that communicates with database in a .php file, not in javascript (remember, javascript is a client side, it executes on client machine, e.g. browser, while php executes on server). Your SQL should never be written in javascript. Client side code cannot communicate with a database directly, only through server side coding. To accomplish that, you must return a value of PHP script getCities.php back to the client(javascript) as a HTTP response.
When you send a HTTP request to some .php file, that scripts executes on a server, and everything that you said "echo" or "print", on the end of script, is automaticaly sent as HTTP response. You don't actualy have to write any code to send a HTTP response. Its done automaticaly. You just have to echo/print whatever you need on the client side. In your case, you need to print options for particular country.
How the script knows for which country it needs to select cities from database?
Well, you send HTTP request with a parameter "country". That is what you Form is doing automaticaly when you submit it. All HTML tags that are inside Form, and have a name attribute set, are gonna be send in HTTP request as parameters. But, since you cannot use submit, you must do this manualy.
To send a parameter inside HTTP GET request is very simple.
Have a look at the following url:
localhost/getCities?country=countryX&someOtherParam=something&myThirdParam=something3
On server side, the following variables are gonna be populated:
$_GET["country"] // value is 'countryX'
$_GET["someOtherParam"] // value is 'something'
$_GET["myThirdParam"] // value is 'something3'
To learn more about how GET and POST works, and what is the difference, check this
Get started by creating a getCities.php file, and copy paste the code that communicates with database and generates city options. It's basically what you already did, you just have to put that code in separate .php file. So, when a client (browser) asks for a list of cities in particular country, you are going to send a HTTP request (using httpGetAsync() function) to get that list from the server.
In your index.php copy paste this script
<script>
function populateCities(citiesSelectBoxOptions){
document.getElementById("city").innerHTML = citiesSelectBoxOptions;
}
function httpGetAsync(theUrl, callback)
{
alert(theUrl);
var xmlHttp = new XMLHttpRequest();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4 && xmlHttp.status == 200)
callback(xmlHttp.responseText);
}
xmlHttp.open("GET", theUrl, true); // true for asynchronous
xmlHttp.send(null);
}
</script>
Next, put onchange attribute on select box, remember, its all lower case, not onChange.
<select name="country" id="country" onchange="httpGetAsync('localhost/getCities?country=' + this.value, populateCities)">
For any question just ask... :)
Well, I suppose one way to do it would be with jQuery.
There's probably a few different ways to do this, but what you could do, is load all the cities into the city drop-down, regardless of country, but change the printf
for the city options like this.
$query = "SELECT city, country FROM cities";
....
while($myrow = pg_fetch_assoc($result)) {
printf ("<option class="$myrow[country] city_select" value=$myrow[city]>$myrow[city]</option>");
}
And then in the javascript for the page, have something like
$('#country').bind('change', function(){
var country = $(this).val();
$('#city option.city_select').hide();
$('#city option.'+country+'').show();
});
It's not necessarily the most elegant solution, though.
You are missing the quotes inside your option, it should be something like
<option value=$myrow['city']>$myrow['city']</option>
try that