Apprenez à créer un formulaire d'adresse complet avec des listes déroulantes pays → région → ville en utilisant les endpoints select de CountryDataAPI.
Ce guide vous montre comment créer des inputs select en cascade pour :
Les endpoints select sont optimisés pour les formulaires, ne retournant que les champs id et name pour une taille de payload minimale et des performances maximales.
D'abord, chargez tous les pays au chargement de votre page. Les pays changent rarement, vous pouvez donc mettre ces données en cache dans localStorage pour de meilleures performances.
const API_KEY = 'votre-cle-api';
const BASE_URL = 'https://api.countrydataapi.com/v1';
async function loadCountries() {
try {
const response = await fetch(
`${BASE_URL}/select/countries?apikey=${API_KEY}&lang=fr`
);
const { success, data, error } = await response.json();
if (!success) {
console.error('Erreur API:', error);
return;
}
const countrySelect = document.getElementById('country');
data.forEach(country => {
const option = new Option(country.name, country.id);
countrySelect.add(option);
});
} catch (err) {
console.error('Erreur Réseau:', err);
}
}
// Appeler au chargement de la page
document.addEventListener('DOMContentLoaded', loadCountries);
Astuce : Mettez la liste des pays en cache dans localStorage pour éviter les appels API répétés. Les pays ne changent pas fréquemment !
Quand un utilisateur sélectionne un pays, chargez les régions/provinces correspondantes et réinitialisez la liste déroulante des villes.
document.getElementById('country').addEventListener('change', async (e) => {
const countryId = e.target.value;
const stateSelect = document.getElementById('state');
const citySelect = document.getElementById('city');
// Réinitialiser les listes déroulantes région et ville
stateSelect.innerHTML = '<option value="">Sélectionnez une région...</option>';
citySelect.innerHTML = '<option value="">Sélectionnez une ville...</option>';
stateSelect.disabled = true;
citySelect.disabled = true;
if (!countryId) return;
try {
const response = await fetch(
`${BASE_URL}/select/states?apikey=${API_KEY}&country=${countryId}&lang=fr`
);
const { success, data, error } = await response.json();
if (!success) {
console.error('Erreur API:', error);
return;
}
data.forEach(state => {
stateSelect.add(new Option(state.name, state.id));
});
stateSelect.disabled = false;
} catch (err) {
console.error('Erreur Réseau:', err);
}
});
Enfin, chargez les villes quand une région est sélectionnée.
document.getElementById('state').addEventListener('change', async (e) => {
const stateId = e.target.value;
const citySelect = document.getElementById('city');
// Réinitialiser la liste déroulante ville
citySelect.innerHTML = '<option value="">Sélectionnez une ville...</option>';
citySelect.disabled = true;
if (!stateId) return;
try {
const response = await fetch(
`${BASE_URL}/select/cities?apikey=${API_KEY}&state=${stateId}&lang=fr`
);
const { success, data, error } = await response.json();
if (!success) {
console.error('Erreur API:', error);
return;
}
data.forEach(city => {
citySelect.add(new Option(city.name, city.id));
});
citySelect.disabled = false;
} catch (err) {
console.error('Erreur Réseau:', err);
}
});
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Formulaire d'Adresse - CountryDataAPI</title>
<style>
body {
font-family: system-ui, -apple-system, sans-serif;
max-width: 600px;
margin: 50px auto;
padding: 20px;
}
.form-group {
margin-bottom: 20px;
}
label {
display: block;
margin-bottom: 8px;
font-weight: 600;
color: #333;
}
select {
width: 100%;
padding: 10px;
border: 2px solid #e2e8f0;
border-radius: 6px;
font-size: 16px;
background-color: white;
cursor: pointer;
}
select:disabled {
background-color: #f7fafc;
cursor: not-allowed;
opacity: 0.6;
}
select:focus {
outline: none;
border-color: #3b82f6;
}
button {
background-color: #3b82f6;
color: white;
padding: 12px 24px;
border: none;
border-radius: 6px;
font-size: 16px;
font-weight: 600;
cursor: pointer;
width: 100%;
}
button:disabled {
background-color: #cbd5e0;
cursor: not-allowed;
}
</style>
</head>
<body>
<h1>Formulaire d'Adresse</h1>
<form id="address-form">
<div class="form-group">
<label for="country">Pays *</label>
<select id="country" name="country" required>
<option value="">Sélectionnez un pays...</option>
</select>
</div>
<div class="form-group">
<label for="state">Région *</label>
<select id="state" name="state" required disabled>
<option value="">Sélectionnez une région...</option>
</select>
</div>
<div class="form-group">
<label for="city">Ville *</label>
<select id="city" name="city" required disabled>
<option value="">Sélectionnez une ville...</option>
</select>
</div>
<div class="form-group">
<label for="street">Adresse *</label>
<input type="text" id="street" name="street" required
style="width: 100%; padding: 10px; border: 2px solid #e2e8f0; border-radius: 6px;">
</div>
<button type="submit">Envoyer l'Adresse</button>
</form>
<script src="address-form.js"></script>
</body>
</html>
Gérez la soumission du formulaire pour obtenir les valeurs sélectionnées :
document.getElementById('address-form').addEventListener('submit', (e) => {
e.preventDefault();
const formData = new FormData(e.target);
const address = {
country: formData.get('country'),
state: formData.get('state'),
city: formData.get('city'),
street: formData.get('street')
};
console.log('Adresse soumise:', address);
// Envoyez à votre backend ou traitez selon vos besoins
// fetch('/api/save-address', {
// method: 'POST',
// headers: { 'Content-Type': 'application/json' },
// body: JSON.stringify(address)
// });
});
Cette implémentation est très efficace en termes d'utilisation de tokens :
Exemple : Un utilisateur remplissant le formulaire complètement utilise seulement 3 tokens au total.
Les pays ne changent pas souvent. Mettez-les en cache dans localStorage :
async function loadCountries() {
const cached = localStorage.getItem('countries');
if (cached) {
const data = JSON.parse(cached);
populateCountrySelect(data);
return;
}
const response = await fetch(
`${BASE_URL}/select/countries?apikey=${API_KEY}&lang=fr`
);
const { success, data } = await response.json();
if (success) {
localStorage.setItem('countries', JSON.stringify(data));
populateCountrySelect(data);
}
}
function populateCountrySelect(countries) {
const select = document.getElementById('country');
countries.forEach(country => {
select.add(new Option(country.name, country.id));
});
}
Affichez un retour visuel pendant le chargement des données :
async function loadStates(countryId) {
const stateSelect = document.getElementById('state');
stateSelect.innerHTML = '<option>Chargement...</option>';
stateSelect.disabled = true;
// ... récupérer les régions
stateSelect.disabled = false;
}
Si vous ajoutez une liste déroulante avec recherche, utilisez le debounce sur l'entrée :
let debounceTimer;
searchInput.addEventListener('input', (e) => {
clearTimeout(debounceTimer);
debounceTimer = setTimeout(() => {
filterOptions(e.target.value);
}, 300);
});
Fournissez toujours des messages d'erreur conviviaux :
try {
// Appel API
} catch (err) {
const select = document.getElementById('state');
select.innerHTML = '<option>Erreur de chargement des régions. Veuillez réessayer.</option>';
}
L'API supporte plusieurs langues. Changez le paramètre lang :
// Espagnol
`${BASE_URL}/select/countries?apikey=${API_KEY}&lang=es`
// Portugais
`${BASE_URL}/select/countries?apikey=${API_KEY}&lang=pt`
// Français
`${BASE_URL}/select/countries?apikey=${API_KEY}&lang=fr`
// Allemand
`${BASE_URL}/select/countries?apikey=${API_KEY}&lang=de`
// Italien
`${BASE_URL}/select/countries?apikey=${API_KEY}&lang=it`
Si vous avez des questions ou avez besoin d'assistance :
Astuce Pro : Pour les applications en production, envisagez d'implémenter un composant dropdown personnalisé avec fonctionnalité de recherche pour gérer les pays avec de nombreuses régions/villes. Des bibliothèques comme Select2, Choices.js ou un autocomplete personnalisé peuvent améliorer significativement l'expérience utilisateur.