Formation PUB030 : Laravel, 2019 Les appels AJAX en Laravel

35.5 Liste filtrée par une liste déroulante, avec appel AJAX


Prenons l'exemple d'une liste de produit qui doit correspondre à la catégorie sélectionnée dans une liste déroulante.

Liste déroulante avec rien de sélectionné

Liste déroulante avec catégorie 1 de sélectionnée

Il serait impensable que le contrôleur passe à la vue la liste de toutes les catégories avec, pour chacune, la liste de tous les produits correspondants. Beaucoup trop de données seraient transférées inutilement.

Les performances seront plus intéressantes si on réussit à aller chercher seulement les produits correspondant à la catégorie sélectionnée. Cependant, la sélection a lieu du côté client, ce qui ne permet pas d'effectuer directement une nouvelle requête à la base de données.

La solution consiste à effectuer un appel AJAX lorsqu'une catégorie est sélectionnée afin d'aller chercher la liste des produits correspondants.

Définition des routes

La première étape consiste à définir les routes.

  • Une première route mènera à la liste des produits, comme on le ferait normalement.
  • Une seconde route fera le lien entre l'attribut action du formulaire contenant la liste déroulante et la méthode d'action qui sera appelée par AJAX.
Fichier routes.php

Route::get('produits', [

    'as' => 'produits.index',

    'uses' => 'ProduitsController@index',

]);

 

// route pour l'appel AJAX 

Route::post('produits/retrouver', [

    'as' => 'produits.retrouverProduits',

    'uses' => 'ProduitsController@retrouverProduits',

]);

Création des vues

Vue qui affiche la liste déroulante

Il faut ensuite créer la vue qui contiendra la liste déroulante et qui accueillera éventuellement la liste des produits.

Remarquez que la liste déroulante est ici mise en forme à l'aide de classes Bootstrap.

Vue produits.index (Blade)

...

{{-- le formulaire utilise la route qui mène à la méthode d'action qui sera appelée par AJAX --}}

<form method="post" action="{{ route('produits.retrouverProduits') }}">

    @csrf

    <div class="form-group row selecthautpage">

        <label for="categorie_id" class="col-form-label col-sm-2">Catégorie&nbsp;: </label>

        <div class="col-sm-4">

            <select class="form-control" id="categorie_id" name="categorie_id">

                <option value="">Veuillez choisir...</option>

                @foreach($categories as $categorie)

                    <option value="{{ $categorie->id }}">{{ $categorie->description }}</option>

                @endforeach

            </select>

        </div>

    </div>

</form>

<div id="donnees"></div>

...

Balises HTML générées par AJAX

Avec la technique utilisée ici, l'appel AJAX se chargera d'appeler une méthode d'action qui aura deux rôles :

  • Elle devra retrouver les données.
  • Elle devra également générer les balises HTML pour afficher ces données.

Pour effectuer cette deuxième tâche, il est intéressant de créer une vue qui représente ce qui devra être affiché. Plutôt que d'afficher cette vue avec une instruction return View(), le contôleur ne fera que récupérer les balises HTML correspondant à la vue avec la méthode render(). L'appel AJAX prendra ce code HTML et l'ajoutera dans la division « donnees », sous la liste déroulante.

Puisqu'il s'agit d'une vue partielle, elle sera placée dans le dossier partials. On ajoutera un sous-dossier qui représente le modèle.

Fichier partials\produits\liste.blade.php (Blade)

<div class="produits">

    @if ($produits->count() > 0)

        <table class="table">

            <thead>

            <tr>

                <th>Code</th>

                <th>Description</th>

            </tr>

            </thead>

            <tbody>

            @foreach($produits as $produit)

                <tr>

                <th>{{ $produit->code }}</th>

                <th>{{ $produit->description }}</th>

                </tr>

            @endforeach

            </tbody>

        </table>

    @else

        <p>Il n'y a présentement aucun produit pour cette catégorie.</p>

    @endif

</div>

Création des méthodes d'action

Première méthode d'action

Une première méthode d'action permettra de retrouver les informations de la liste déroulante et d'afficher la vue correspondante.

Contrôleur Laravel (PHP)

/**

 * Affiche la liste déroulante des catégories. La listes des produits sera fournie par AJAX.

 *

 * @return \Illuminate\View\View

 */

public function index() : View

{

    ...

    $categories = Categorie::orderBy('description')->get();  // retrouve les catégories de la liste déroulante

    return View('produits.index', compact('categories'));

}

Méthode d'action appelée par AJAX

Tous les éléments sont maintenant en place pour définir la méthode d'action qui sera appelée par AJAX.

Contrôleur Laravel (PHP)

/**

 * Génère les balises HTML des produits à afficher pour la catégorie sélectionnée.

 * Méthode appelée via AJAX

 *

 * @return \Illuminate\Http\JsonResponse Chaîne JSON avec variables valide et contenuHTML

 */

public function retrouverProduits() : JsonResponse

{

    ...

    $valide = true;

    $contenuHTML = '';

 

    // retrouve l'information passée par AJAX

    $id = $_POST['categorie_id'];

 

    // génère les balises HTML avec la liste des produits 

    try {

        $produits = Produit::where('categorie_id', $id)->orderBy('code')->get();   // sera une collection vide si le select est sur "Veuillez choisir..."

        $contenuHTML = View('partials.produits.liste', compact('produits'))->render();

        ...

    }

    catch(\Throwable $e) {

        \Log::error("Erreur inattendue. ", [$e]);

        $valide = false;

    }

    return response->json(compact('valide','contenuHTML'));

}

Appel AJAX

Finalement, on écrira l'appel AJAX.

jQuery

$(function () {

 

    $('#categorie_id').change(function (event) {

        event.preventDefault();    // peu d'utilité ici mais ce serait nécessaire si l'appel AJAX était généré par un clic sur un bouton

 

        // retrouver les données du formulaire

        var $formulaire = $(this).parents("form:first");     // formulaire dans lequel la balise qui a généré l'appel AJAX était placée

        var donneesFormulaire = $formulaire.serialize();     // donc le jeton anti-CSRF est inclus.

        var actionFormulaire = $formulaire.attr('action');   // l'URL pour l'appel AJAX doit être absolu.

 

        // appel AJAX

        $.ajax({

            type: "POST",

            url: actionFormulaire,

            dataType: "json",

            data: donneesFormulaire

        })

        .done(function (response, textStatus, jqXHR) {

            if (response.valide) {

                ...

                // l'utilisation de render() a placé dans la variable contenuHTML tout le code HTML de la vue

                $('#donnees').html(response.contenuHTML);

            }

            else {

                ...

            }

        })

        .fail(function (jqXHR, textStatus, errorThrown) {

            ...

        });

    });

});

▼Publicité

Veuillez noter que le contenu de cette fiche vous est partagé à titre gracieux, au meilleur de mes connaissances et sans aucune garantie.
Merci de partager !
Soumettre