Apprendre à créer une requête AJAX avec JavaScript (fetch, async/await) dans une application Symfony pour afficher en temps réel la disponibilité des ateliers, sans créer d'API séparée.
JavaScript fait une requête AJAX
Route retourne du JSON
Données de disponibilité
Interface actualisée
// Dans votre contrôleur AtelierController #[Route('/ateliers/disponibilite', name: 'ateliers_disponibilite', methods: ['GET'])] public function getDisponibilite( AtelierRepository $atelierRepository, ReservationRepository $reservationRepository ): JsonResponse { // Logique de traitement... return new JsonResponse([ 'success' => true, 'ateliers' => $disponibilites, 'timestamp' => date('Y-m-d H:i:s') ]); }
// Pour chaque atelier foreach ($ateliers as $atelier) { // Compter les réservations existantes $reservationsCount = $reservationRepository->countByAtelier($atelier->getId()); // Calculer les places disponibles $placesDisponibles = $atelier->getCapaciteMax() - $reservationsCount; $disponibilites[] = [ 'id' => $atelier->getId(), 'nom' => $atelier->getNom(), 'placesDisponibles' => max(0, $placesDisponibles), 'complet' => $placesDisponibles <= 0, ]; }
{
"success": true,
"ateliers": [
{
"id": 1,
"nom": "Atelier Poterie",
"placesDisponibles": 5,
"complet": false
}
],
"timestamp": "2025-01-15 14:30:22"
}
// Fonction principale avec async/await async function updateDisponibilite() { try { console.log('Mise à jour de la disponibilité...'); // Requête AJAX avec fetch const response = await fetch('/ateliers/disponibilite', { method: 'GET', headers: { 'Content-Type': 'application/json', 'X-Requested-With': 'XMLHttpRequest' } }); // Vérifier la réponse if (!response.ok) { throw new Error(`Erreur HTTP: ${response.status}`); } // Parser le JSON const data = await response.json(); // Mettre à jour l'interface updateAteliersDisplay(data.ateliers); } catch (error) { console.error('Erreur:', error); } }
// Mettre à jour l'affichage pour chaque atelier function updateAteliersDisplay(ateliers) { ateliers.forEach(atelier => { const atelierId = atelier.id; // Trouver les éléments dans le DOM const badge = document.querySelector( `.disponibilite-badge[data-atelier-id="${atelierId}"]` ); // Mettre à jour le badge if (atelier.complet) { badge.textContent = 'Complet'; badge.classList.add('badge-danger'); } else { badge.textContent = `${atelier.placesDisponibles} places`; badge.classList.add('badge-success'); } }); }
// Configuration de l'intervalle const REFRESH_INTERVAL = 5000; // 5 secondes let updateInterval; // Démarrer les mises à jour automatiques function startAutoUpdate() { // Première mise à jour immédiate updateDisponibilite(); // Puis mise à jour périodique updateInterval = setInterval(updateDisponibilite, REFRESH_INTERVAL); } // Optimisation : arrêter quand l'onglet n'est pas visible document.addEventListener('visibilitychange', function() { if (document.visibilityState === 'visible') { startAutoUpdate(); } else { clearInterval(updateInterval); } });
async function updateDisponibilite() { try { const response = await fetch('/ateliers/disponibilite'); // Vérifier le statut HTTP if (!response.ok) { throw new Error(`Erreur HTTP: ${response.status}`); } const data = await response.json(); // Vérifier la structure de la réponse if (data.success) { updateAteliersDisplay(data.ateliers); updateTimestamp(data.timestamp); } else { console.error('Erreur dans la réponse:', data); } } catch (error) { console.error('Erreur lors de la mise à jour:', error); updateTimestamp('Erreur de connexion'); } }
// Dans ReservationRepository.php public function countByAtelier(int $atelierId): int { return $this->createQueryBuilder('r') ->select('COUNT(r.id)') ->where('r.atelier = :atelierId') ->andWhere('r.statut != :statut_annule') ->setParameter('atelierId', $atelierId) ->setParameter('statut_annule', 'annule') ->getQuery() ->getSingleScalarResult(); } // Version optimisée pour tous les ateliers en une requête public function getStatistiquesReservations(): array { return $this->createQueryBuilder('r') ->select('a.id as atelier_id, COUNT(r.id) as nb_reservations') ->leftJoin('r.atelier', 'a') ->groupBy('a.id') ->getQuery() ->getResult(); }
Vous maîtrisez maintenant AJAX avec Symfony !