I'm building a dependent dropdown for country, state and city. It's not going very well. I've done extensive research on the subject on Stackoverflow and other sites on the web for the past few days and have not been able to get the '#state' select object to populate states based on the selected '#country' select object which is populating countries from json just fine. The states are not populating after the country is selected based on the 'change' method. I have an 'if' statement which says, 'if the selected #country === 'US' (which displays as North America), then load the US states and territories .json file.
After fiddling around with the code, I have finally been able to get the '#state' dropdown to at least display 'object [Object]', so I know I'm getting closer to a solution. I'm not quite sure why it's displaying 'object[Object]' in the state dropdown. It may be a 'type' error of some sort where json is being displayed as an object instead of a string as it should but I don't understand how to fix this in the context of my code.
Any help would be greatly appreciated.
Here is the HTML:
<!doctype html>
<html>
<head>
<title>Country->State->City</title>
</head>
<body>
Country:
<select id="country">
<pre><option selected value="base">Select Country</option><pre>
</select>
State:
<select id="state">
<option selected value="base">Select state</option>
</select>
City:
<select id="city">
<option selected value="base">Select City</option>
</select>
<script type = "text/javascript" src="jquery-2.2.4.min.js"></script>
<script type = "text/javascript" src="custom.js"></script>
</body>
</html>
jQuery
$(function(){
let countryOptions;
let stateOptions;
let gaCitiesOps;
$.getJSON('countries.json',function(data){
$.each(data, function(i,country) {
countryOptions+=
'<option value= "'+country.code+'">'
+country.name+
'</option>';
});
$('#country').html(countryOptions);
});
$("#country").change(function(){
if($(this).val()==="US"){
$.getJSON('us_states.json',function(data){
$.each(data, function(stateCode,stateName) {
stateOptions+='<option value="'+stateCode+'">'
+stateName+
'</option>';
});
$('#state').html(stateOptions);
});
}
});
$("#state").change(function(){
if($(this).val()==="GA"){
$.getJSON('GA_cities.json',function(data){
$.each(data, function(statecode,city) {
gaCitiesOps +='<option value="'+statecode+'">'
+city+
'</option>';
});
$('#city').html(gaCitiesOps);
});
}
});
});
Countries.json
[
{
"code": "US",
"name": "North America"
},
{
"code": "AG",
"name": "Antigua"
},
{
"code": "AU",
"name": "Australia"
},
{
"code": "AT",
"name": "Austria"
},
{
"code": "BG" ,
"name": "Bulgaria"
},
{
"code": "CA",
"name": "Canada"
},
.....ect
us_states.json
[
{
"stateCode": "AL",
"name": "Alabama"
},
{
"stateCode": "AR",
"name": "Arkansas"
},
{
"stateCode": "AS",
"name": "American Samoa"
},
{
"stateCode": "AZ",
"name": "Arizona"
},
{
"stateCode": "CA",
"name": "California"
},
.....etc
GA_cities.json
[
{
"code": "ALB",
"name": "ALBANY"
},
{
"code": "AMR",
"name": "AMERICUS"
},
{
"code": "ATH",
"name": "ATHENS"
},
{
"code": "ATL",
"name": "ATLANTA"
},
{
"code": "AUG",
"name": "AUGUSTA"
},
{
"code": "BAI",
"name": "BAINBRIDGE"
},
....etc
Thanks for your consideration!
You're using $.each incorrectly. First argument is the index/key, second is the value. In your case you iterate over array of objects - so first argument is an index and second is each contained object. Use this code for states:
$.each(data, function(index,stateObj) {
stateOptions+='<option value="'+stateObj.stateCode+'">'
+stateObj.name+
'</option>';
});
$('#state').html(stateOptions);
});
And this for cities:
$("#state").change(function(){
if($(this).val()==="GA"){
$.getJSON('GA_cities.json',function(data){
$.each(data, function(index,city) {
gaCitiesOps +='<option value="'+city.code+'">'
+city.name+
'</option>';
});
$('#city').html(gaCitiesOps);
});
}
});
You can also add options using JS APIs which is slightly better than constructing the entire options HTML as a string and dumping it into html(). See this question for the alternative methods.
console.log() is your best friend. Try logging the values you get from $.each and you will know why you're getting [object Object].
$.each(data, function(stateCode, stateName));
Output is stateCode 0, stateName {stateCode: "AL", name: "Alabama"}
$.each arguments are (key, value) and you are looping over an array so key (stateCode in this case) is index of the array.
ES6; If you wanna be fancy you can destructure the arguments to
$.each(key, {stateCode, name});
Related
Please tell me why if you add a value to the search, then the span is not filled? If you leave only the if, then everything works.
I can't understand what the problem might be, since this is a common condition, if the code is found, then it displays the country in the span.
Without the else:
var phones = [{
"country": "UA",
"code": "+380"
},
{
"country": "RU",
"code": "+7"
},
{
"country": "MD",
"code": "+373"
}
];
$(".phone").keyup(function() {
var val = $(this).val();
phones.find(function(phones) {
if (phones.code == val) {
$("#county").text(phones.country);
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="county"></span>
<input type="text" class="phone">
With else:
var phones = [{
"country": "UA",
"code": "+380"
},
{
"country": "RU",
"code": "+7"
},
{
"country": "MD",
"code": "+373"
}
];
$(".phone").keyup(function() {
var val = $(this).val();
phones.find(function(phones) {
if (phones.code == val) {
$("#county").text(phones.country);
} else {
$("#county").text("no");
}
});
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="county"></span>
<input type="text" class="phone">
Because .find is looping through all your objects. If you search for lets say +7, it will show no then RU then no again, so it overwrites the value while without the else it gets in once and stays like that without replacing.
The solution here is to finish with your find first, and then do the if.
I would do something like this:
var phones = [{
"country": "UA",
"code": "+380"
},
{
"country": "RU",
"code": "+7"
},
{
"country": "MD",
"code": "+373"
}
];
$(".phone").keyup(function () {
var val = $(this).val();
var phoneObj = phones.find(x => x.code == val);
if (phoneObj == undefined) {
$("#county").text("no");
}
else {
$("#county").text(phoneObj.country);
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="county"></span>
<input type="text" class="phone">
That is because the next value is not same as the input code, so the else loop is executed & shows no.
Explanation: The array method iterates all the object. So when the input matches it shows the country. But when the next object is under iteration it does not match with the input value. Hence the previous text is over written.
The input is +7 and matches with the code and showing the country. But immediately after that +7 is compared with next object and the code does not match. So else loop is executed.
When using only if nothing happens when the code and input value does not match.
I have a JSON file with a list of countries which has 2 keys: "name" and "areacode". I have dropdown with a list of options that has a value attr witch is the same as the "name" key in the JSON file.
Long story short: I want to display the "areacode" value in the json file when the selected option in the dropdown matches the "name" value in the JSON file
UPDATE
I have pasted the code here: http://codepen.io/sarfehjou/pen/RpKMWE
The only difference is that in my solution I have to get the JSON file by a url
HTML
<select>
<option value="Afghanistan GLOBAL">Afghanistan GLOBAL</option>
<option value="Albenter code hereania">Albania</option>
<option value="Algeria">Algeria</option>
<option value="American Samoa">American Samoa</option>
<option value="Andorra">Andorra</option>
</select>
Script
var list = {
"countries": [
{
"name": "Afghanistan GLOBAL",
"areacode": ""
},
{
"name": "Albania",
"areacode": ""
},
{
"name": "Algeria",
"areacode": ""
},
{
"name": "American Samoa",
"areacode": ""
},
{
"name": "Andorra",
"areacode": ""
}
]
}
Your question is quite vague as already established, i.e. not sure what you need to do with area code and stuff? anyway this is what i could work out:
basically added an event listener on the select and whenever you change it, looks up the value from list (the list can be from the server or cached).
Have a look, if you get more ideas asks some more.
var list = {
"countries": [
{
"name": "Afghanistan GLOBAL",
"areacode": "8787"
},
{
"name": "Albania",
"areacode": "446"
},
{
"name": "Algeria",
"areacode": "212"
},
{
"name": "American Samoa",
"areacode": "767"
},
{
"name": "Andorra",
"areacode": "5454"
}
]
}
var countrySelect = document.getElementById('countrySelect');
countrySelect.addEventListener('change', function(e) {
console.log(this.value);
console.log(findAreaCode(this.value));
});
function findAreaCode(name) {
var resultItems = list.countries.filter(function(currentItem) {
return currentItem.name == name;
})
console.log(resultItems[0]);
return resultItems[0]? resultItems[0].areacode: 'N/A';
}
<select id="countrySelect">
<option value="Afghanistan GLOBAL">Afghanistan GLOBAL</option>
<option value="Albenter code hereania">Albania</option>
<option value="Algeria">Algeria</option>
<option value="American Samoa">American Samoa</option>
<option value="Andorra">Andorra</option>
</select>
I have pasted the code her: http://codepen.io/sarfehjou/pen/RpKMWE
The only different is that in my solution I have to get the json file by a url
<select>
<option value="Afghanistan GLOBAL">Afghanistan GLOBAL</option>
<option value="Albenter code hereania">Albania</option>
<option value="Algeria">Algeria</option>
<option value="American Samoa">American Samoa</option>
<option value="Andorra">Andorra</option>
</select>
var list = {
"countries": [
{
"name": "Afghanistan GLOBAL",
"areacode": ""
},
{
"name": "Albania",
"areacode": ""
},
{
"name": "Algeria",
"areacode": ""
},
{
"name": "American Samoa",
"areacode": ""
},
{
"name": "Andorra",
"areacode": ""
}
]
}
To answer your question, you can do this,
$.getJSON("http://api/somejsonfile/",function(data){
// Initializing an empty array
var options=[];
// Running a loop on the response JSON and adding the options to a string array
$.each(data.countries,function(id,eachcountry){
options.push("<option value='"+eachcountry.areacode+"'>"+eachcountry.name+"</option>");
});
// Joining the string and replacing it inside the select element
$(".dropdown").html(options.join(""));
});
This is a rough implementation so there might be some syntactical issues!!
Adding a simple example
$(document).ready(function(){
// This is a sample country code JSON from Github
$.getJSON("https://gist.githubusercontent.com/Goles/3196253/raw/9ca4e7e62ea5ad935bb3580dc0a07d9df033b451/CountryCodes.json",function(data){
// Initializing an empty array
var options=[];
// Running a loop on the response JSON and adding the options to a string array
$.each(data,function(id,eachcountry){
options.push("<option value='"+eachcountry.dial_code+"'>"+eachcountry.name+"</option>");
});
// Joining the string and replacing it inside the select element
$(".dropdown").html(options.join(""));
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select class="dropdown">
<option value="">Select</option>
</select>
I have json code that comes out like:
{
"player": [{
"player_id": "1",
"player_name": "Maxfly",
"player_image": "res_573fc05f57c0e.png",
"player_background_image": "images/player_backgrounds/581046687fd89.jpg",
"player_info": "",
"player_region": "North America",
"player_teams": [{
"id": "1",
"team_name": "Test Team",
"team_link": "test-team"
}, {
"id": "65",
"team_name": "Test Team 2",
"team_link": "test-team-2"
}]
}]
}
I've managed to get the player_id and player_name etc. My question is how to I just get the teams? I've tried the following:
$.getJSON("jsonlink",
function(data) {
$.each(data.player.player_teams, function(i,player_team){
var append_data = "<div class='item team_item'><div class='row'><div class='col col_img'><a href='/t/" + player_team.team_name + "' ></a></div></div></div>";
$("#popin-container").append($('<div>' + append_data + '</div>').hide().fadeIn(800));
});
});
Trying to figure out what I'm doing wrong. Is my json object correct?
Thanks!
Your data.player.player_teams is wrong, as data.player is an array, and not an object. You need to loop through it, or in simple way, you need to attach a [0] like this:
$.each(data.player[0].player_teams, function(i, player_team) {
$scope.StateList = {"States": [
{
"Id": 1,
"Code": "AL",
"Name": "Alabama"
},
{
"Id": 2,
"Code": "AK",
"Name": "Alaska"
},
{
"Id": 3,
"Code": "AZ",
"Name": "Arizona"
},
{
"Id": 4,
"Code": "AR",
"Name": "Arkansas"
}]}
And I display the data as follows in an html select:
<select ng-model="Address.State"
ng-options="state.Code as state.Name for state in StateList.States"></select>
Right now this will display the full name of the state in the select like "Arizona". What I would like to do is format the display without adding a new property to the object, to use something like (state.Name, state.Code, state.Id). I am trying to use filters of some sort to do this but I have not figured it out yet. Thanks for your suggestions.
plunker
There are three ways that you can achieve this. The first is to just set the value you want inline:
<select ng-model="Address.State" ng-options="state.Code as (state.Name + ', ' + state.Code + ', ' + state.Id) for state in StateList.States"></select>
Or you can do the same thing, but as a function in your controller:
$scope.display = function(state) {
return state.Name + ', ' + state.Code + ', ' + state.Id;
}
<select ng-model="Address.State" ng-options="state.Code as display(state) for state in StateList.States"></select>
Or you can create a filter (as per PSLs answer)
Try creating a small format filter:-
app.filter('stateName', function() {
return function(itm) {
return [itm.Name , itm.Code, itm.Id].join();
}});
and use it as:-
ng-options="state.Code as (state|stateName) for state in StateList.States
Plnkr
New to JSON so I'll do my best here. I have a JSON object called HUDS. Below are 2 sample nodes (by the way, can I call these nodes in JSON like in XML?).
var HUDS = [
{
"DISTRICT": "100",
"BIOS": "BROWN",
"AREA_KM": "3663.158164",
"AREA_MI": "1414.347616",
"NAME": "100",
"REG": "1",
"ACRES": "905182",
"EMU_Name": "Purcell",
"Shape_Leng": "299746.4938",
"Shape_Area": "3663158164",
},
{
"DISTRICT": "101",
"BIOS": "THIER",
"AREA_KM": "1507.774765",
"AREA_MI": "582.152762",
"NAME": "101",
"REG": "1",
"ACRES": "372578",
"EMU_Name": "Salish",
"Shape_Leng": "229150.0655",
"Shape_Area": "1507774766",
}
]
I have a drop down form that will be used to specify a value specific to the "BIOS" field in my JSON. For example the user could select BROWN from the dropdown menu.
I'd then like to create a var that can be used to fill in a div. For example when the user selects BROWN I'd like my div to fill with the value from "EMU_Name"
I know this is wrong but maybe it conveys what I am going for
function dropDownAction(){
var tempBios=document.BIOSForm.BIOS.value;
var tempEmuValue=HUDS.BIOS==tempBios.EMU_Name;
document.getElementById("mydiv").innerHTML=tempEmuValue;
}
Try:
<form name="BIOSForm">
<select name="BIOS" onchange="dropdownaction();">
<option value="BROWN">BROWN</option>
<option value="THEIR">THEIR</option>
</select>
</form>
<div id="emuname">
</div>
<script type='text/javascript'>
var HUDS = [
{
"DISTRICT": "100",
"BIOS": "BROWN",
"AREA_KM": "3663.158164",
"AREA_MI": "1414.347616",
"NAME": "100",
"REG": "1",
"ACRES": "905182",
"EMU_Name": "Purcell",
"Shape_Leng": "299746.4938",
"Shape_Area": "3663158164",
},
{
"DISTRICT": "101",
"BIOS": "THIER",
"AREA_KM": "1507.774765",
"AREA_MI": "582.152762",
"NAME": "101",
"REG": "1",
"ACRES": "372578",
"EMU_Name": "Salish",
"Shape_Leng": "229150.0655",
"Shape_Area": "1507774766",
}
]
function dropdownaction(){
for(var x=0;x<HUDS.length;x++){
var tempBios = document.BIOSForm.BIOS.value;
if(tempBios == HUDS[x].BIOS){
document.getElementById("emuname").innerHTML = HUDS[x].EMU_Name;
break;
}
}
}
</script>