Кастомный выпадающий список стран при помощи API
Подскажите пожалуйста, как правильно сделать кастомный список стран используя API. Вот fetch код:
// country list generate
const countryList = document.querySelector('.form-list.country');
fetch('https://restcountries.com/v3.1/all').then(res => {
return res.json();
}).then(data => {
let output = '';
data.forEach(country => {
output += `<li class="form-item" data-value="${country.name.common}">${country.name.common}</li>`;
countryList.innerHTML = output;
});
}).catch(err => {
console.log(err);
});
полный код html, css, js Во втором списке "Country" список формируется, но название страны не поставляется в форму, а атрибут "data-value="" " в инпут ниже. В первом списке "Guests Amount" все ок, т.к. данные прописаны в html. Нужен такой же со странами.
Сразу скажу, с тегом select все работает, но мне нужна стилизованная выпадашка. Заранее спасибо.
Ответы (1 шт):
проблема заключается в том, что
const openItems = openList.querySelectorAll('.form-item');
Находит два списка, НО так как второй список (страны) через fetch, то он просто еще не успевает загрузится и от рисоваться в DOM. querySelectorAll срабатывает быстрее, поэтому во втором списке ничего нет
Данную задачу можно сделать так, немного переделал логику
document.querySelectorAll('.select-btn').forEach(function (selectWrapper) {
selectWrapper.addEventListener('click', function(e){
const openList = selectWrapper.nextElementSibling;
const hiddenInput = openList.nextElementSibling;
const openItems = openList.querySelectorAll('.form-item');
openList.classList.toggle('open');
if (e.target != selectWrapper) {
openList.classList.remove('open');
}
openItems.forEach(function(item) {
item.addEventListener('click',function(){
selectWrapper.innerText = this.innerText;
openList.classList.remove('open');
hiddenInput.value = this.dataset.value;
})
})
})
})
// country list generate
const countryList = document.querySelector('.form-list.country');
fetch('https://restcountries.com/v3.1/all').then(res => {
return res.json();
}).then(data => {
let output = '';
data.forEach(country => {
output += `<li class="form-item" data-value="${country.name.common}">${country.name.common}</li>`;
countryList.innerHTML = output;
});
}).catch(err => {
console.log(err);
});
.form {
font-family: 'Arial', sans-serif;
width: 500px;
background: #FFFFFF;
padding: 50px 20px;
display: flex;
flex-direction: column;
}
.form-select {
width: 100%;
position: relative;
margin-bottom: 20px;
}
.form-list {
display: none;
position: absolute;
top: 45px;
left: 0;
right: 0;
background-color: #ccc;
font-size: 20px;
line-height: 1;
color: #000;
border-radius: 8px;
list-style: none;
padding: 0;
margin: 0;
z-index: 2;
}
.form-list.open {
display: block;
}
.form-list.country {
height: 400px;
overflow-y: scroll;
}
.form-item {
padding: 6px 20px;
cursor: pointer;
background-color: #ccc;
transition: all .2s;
}
.form-item:hover {
background-color: #f3f0f0;
}
.form-item:last-child {
border-radius: 0 0 8px 8px;
padding-bottom: 10px;
}
.form-item:first-child {
padding-top: 10px;
border-radius: 8px 8px 0 0;
}
.hidden-input {
/* display: none; */
}
.select-btn {
display: inline;
width: 100%;
text-align: left;
background-color: #ccc;
border-radius: 8px;
padding: 6px 20px;
border: 1px solid #ccc;
font-size: 20px;
line-height: 1.3;
color: #000;
cursor: pointer;
}
.select-btn:focus {
outline: none;
border: 1px solid #999;
}
<form class="form">
<div class="form-select">
<button class="select-btn" type="button">Guests Amount</button>
<ul class="form-list">
<li class="form-item" data-value="onePerson">1 Guest</li>
<li class="form-item" data-value="twoPerson">2 Guests</li>
<li class="form-item" data-value="threePerson">3 Guests</li>
<li class="form-item" data-value="fourPerson">4 Guests</li>
<li class="form-item" data-value="fivePerson">5 Guests</li>
</ul>
<input type="text" class="hidden-input">
</div>
<div class="form-select">
<button class="select-btn" type="button">Country</button>
<ul class="form-list country"></ul>
<input type="text" class="hidden-input">
</div>
</form>