const url = "https://restcountries.eu/rest/v2/all"
fetch(url)
.then(function(response){
return response.json()
})
.then(function(data){
console.log(data)
worldRegion(data)
})
function worldRegion(myData) {
var myArray = []
for(var i = 0; i < myData.length; i++) {
myArray.push(myData[i].region)
}
var region = myArray.filter(onlyUnique);
var regionOptgroup = ""
for(var i = 0; i < region.length; i++) {
regionOptgroup += `<optgroup value=${region[i]} label="${region[i]}">${region[i]}</optgroup>`
}
document.querySelector("select").innerHTML = regionOptgroup
const nodeList = document.querySelectorAll("optgroup")
console.log(nodeList)
var options = ""
for(var i = 0; i < myData.length; i++) {
for(var j = 0; j < nodeList.length; j++) {
if(myData[i].region === nodeList[j].value)
options += `<option value="${myData[i].name}">${myData[i].name}</option>`
}
}
document.querySelector("select").innerHTML = options
}
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>what language do they speak</title>
</head>
<body>
<select class="" name="">
</select>
<br>
</body>
<script src="index.js" type="text/javascript">
</script>
</html>
I’ve created 6 different opt group elements, namely Asia, Europe, Africa, Oceania, Americas and Polar, using a for loop. Then I’ve nested the opt group elements in question within a select element. I’ve also stored that selection of elements or node list in a variable named nodeList.
I’m trying to replicate a more or less similar approach in order to nest option elements within the opt group elements according to the region a country belongs to. So the option element with InnerHTML Singapore and “value = Asia” would be nested within the Asia opt group element. And so and so forth for 250 option elements.
What I’ve been trying to do is to extract the value of each opt group element so as to nest my option elements accordingly. Hence the following condition in my if statement: (=myData[i].region === nodeList[j].value). However, the console also throws the following error: “index.js:34 Uncaught (in promise) TypeError: Cannot read property 'value' of undefined at worldRegion (index.js:34) at index.js:10”
And then it’s becoming sort of spaghetti code.
I’ve tried to lay the problem out as intelligibly as possible. But please don’t hesitate to leave a comment should you need further clarification.
I know I probably need to work on indentation and elegance but first off I’d like my code to work
const url = "https://restcountries.eu/rest/v2/all"
fetch(url)
.then(function(response){
return response.json()
})
.then(function(data){
console.log(data)
worldRegion(data)
})
function worldRegion(myData) {
var myArray = []
for(var i = 0; i < myData.length; i++) {
myArray.push(myData[i].region)
}
var region = myArray.filter(onlyUnique);
var regionOptgroup = ""
for(var i = 0; i < region.length; i++) {
regionOptgroup += `<optgroup value=${region[i]} label="${region[i]}">${region[i]}</optgroup>`
}
document.querySelector("select").innerHTML = regionOptgroup
const nodeList = document.querySelectorAll("optgroup")
console.log(nodeList)
var options = ""
for(var i = 0; i < myData.length; i++) {
for(var j = 0; j < nodeList.length; j++) {
}
if(myData[i].region === nodeList[j].value)
options += `<option value="${myData[i].name}">${myData[i].name}</option>`
}
document.querySelector("select").innerHTML = options
}
function onlyUnique(value, index, self) {
return self.indexOf(value) === index;
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>what language do they speak</title>
</head>
<body>
<select class="" name="">
</select>
<br>
</body>
<script src="index.js" type="text/javascript">
</script>
</html>
You could create the optgroup
elements using DOM methods instead of HTML, so that you immediately get the reference to each created element. Store those elements in a Map
keyed by the region name.
Then when you finally create the options, you can look up the region in that Map so to retrieve the reference to the corresponding optgroup
element:
const url = "https://restcountries.eu/rest/v2/all";
(async () => {
const response = await fetch(url);
const data = await response.json();
let select = document.querySelector("select");
// Create a map, keyed by region
let regions = new Map(data.map(({region}) => [region, null]));
// Assign an optgroup to each region in that map
for (let region of regions.keys()) {
let optgroup = document.createElement("optgroup");
optgroup.setAttribute("value", region);
optgroup.setAttribute("label", region || "(blank)");
select.appendChild(optgroup);
regions.set(region, optgroup);
}
for (let country of data) {
// Create an option for each country
let option = document.createElement("option");
option.setAttribute("value", country.name);
option.textContent = country.name;
// Append it to the relevant optgroup
regions.get(country.region).appendChild(option);
}
})();
<select class="" name="">
</select>