Reputation: 2062
I have a json
file which consists of countries, and cities per country, in the following structure:
{
"United States": [
"New York",
"Los Angeles",
"San Francisco",
"Baltimore",
"Washington"
],
"England": [
"Manchester",
"Liverpool",
"Newcastle",
"Bradford",
"London"
]
}
On page load I extract the countries and push them into an array
. On country select, I create an array
of cities according to the selected country. The code works with a pre-defined array
, but not with the newly created one. Any ideas?
Jsfiddle here.
HTML:
<div id="countryContainer">
<label>Heroes from country:</label>
<select multiple="multiple" data-placeholder="Select a country" id="countryList"></select>
</div>
<br><br>
<input type="text" id="search">
The JS code is a bit long:
$(document).ready(function () {
var source = [];
$.ajax({
url: "https://api.myjson.com/bins/22mnl",
dataType: "json",
success: function (response) {
response1 = response;
var keys = Object.keys(response);
keys.forEach(function (key) {
source.push(key);
});
console.log(source);
for (var i = 0; i < source.length; i++) {
var option1 = $('<option value=' + source[i] + '>' + source[i] + '</option>');
$("#countryList").append(option1);
}
}
});
});
$('#countryList').select2();
var citiesArray = [];
var citiesObjArr = [];
//creation of array of countries from the json
$("#countryList").on("change", function () {
if ($("#countryContainer li").length > 1) {
console.log("changed");
var selectedCountry = $("#countryList option:selected")[0].innerHTML;
console.log("country selected: " + selectedCountry);
citiesObjArr.length = 0;
citiesArray.length = 0;
createArrayOfCities(selectedCountry);
} else {
console.log("empty");
}
});
//extraction of cities per selected country from the original json and insertion into an array of objects
function createArrayOfCities(key) {
$.ajax({
url: "https://api.myjson.com/bins/22mnl",
dataType: "json",
success: function (response) {
if (response.hasOwnProperty(key)) {
var j = 0;
var i = 0;
response[key].forEach(function (i) {
citiesArray[j] = i;
//CREATION OF THE CITIES OBJECTS ARRAY
citiesObjArr.push({
val: i
});
j++;
});
}
console.log(citiesObjArr);
console.log(typeof (citiesObjArr));
}
});
}
//typeahead autocomplete here
//THIS ARRAY OF OBJECTS WORK, BUT citiesObjArr DOES NOT. WHY??
/*
var data1 = [{
val: "city1111"
}, {
val: "city2222",
}];
*/
var titles = new Bloodhound({
datumTokenizer: function (data) {
return Bloodhound.tokenizers.whitespace(data.val);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
local: citiesObjArr
});
titles.initialize();
$("#search").typeahead({
highlight: true
}, {
name: 'titles',
displayKey: 'val',
source: titles.ttAdapter()
});
Upvotes: 1
Views: 639
Reputation: 8171
The problem is here is that you are loosing access to citiesObjArr
outside of your success callback. To get around this, you can defer your response object:
Inside your change
handler, you can do the following:
$.when(createArrayOfCities())
.then(function(data) {
// Pass in the response and selected country to a new function
handleResponse(data, selectedCountry);
});
You will need to change your createArrayOfCities()
function to the following:
function createArrayOfCities() {
return $.ajax({
url: "https://api.myjson.com/bins/22mnl",
dataType: "json",
success: function (response) {
return response;
}
});
}
NOTE: you might want to change the name of the above function for readability (since it no longer builds the array of cities)
And then you can call the new handleResponse
function:
function handleResponse(response, key) {
if (response.hasOwnProperty(key)) {
var j = 0;
var i = 0;
response[key].forEach(function (i) {
citiesArray[j] = i;
////CREATION OF THE CITIES OBJECTS ARRAY
citiesObjArr.push({
val: i
});
j++;
});
};
var titles = new Bloodhound({
datumTokenizer: function (data) {
return Bloodhound.tokenizers.whitespace(data.val);
},
queryTokenizer: Bloodhound.tokenizers.whitespace,
local: citiesObjArr
});
titles.initialize();
$("#search").typeahead({
highlight: true
}, {
name: 'titles',
displayKey: 'val',
source: titles.ttAdapter()
});
}
Upvotes: 1