Laravel 5

ajax pagination

  • Avatar de ThomasHabets
    Membre depuis :
    14/07/2018
    Messages :
    8

    Bonjour,
    Je recontre actuellement un problème avec mon projet sous Laravel 5.6. Mon but est de créer un moyen à l'utilisateur d'accéder sur une page spécifique à un formulaire. En cliquant sur envoyer, le formulaire est censé envoyer les infos via jQuery pour construire automatiquement une requête mysql brute. Une fois cette requête créée, un appel Ajax de type POST est réalisé afin de passer au controller la requête mysql sous forme de string. De son côté, le controller crée une variable à partir de la méthode paginate() inclue dans Laravel. Il va ensuite retourner une vue "partielle" dans la vue de départ. L'utilisateur a ainsi accès aux articles qu'il a demandé sans rechargement de la page. De ce côté là, tout roule.
    C'est ici que je bloque. Quand l'utilisateur a devant lui les résultats avec la navigation de pagination, les liens vers les autres pages de la pagination ne fonctionnent pas ! L'utilisateur ne peut donc pas voyager entre les pages via ajax.

    Voici mes bouts de code:

    Routes

    Route::get('articles/filter', 'ArticleController@filterx');
    Route::post('articles/request/ajax/articles/filter', 'ArticleController@filtery');
    Route::get('articles/request/ajax/articles/filter', 'ArticleController@filtery');

    Controller

    public function filterx() { // get filter page
    return view('filter');
    }

    public function filtery(Request $request) { // filter ajax function
    $articles = Article::paginate(2);
    if($request->ajax()) {
    // partial view returned in html
    return $html = view('filterResults', compact('articles'));
    }
    }

    Vues
    filter.blade.php

    @extends('layouts/app')

    @section('title')
    Title
    @endsection

    @section('content')
    <div class="container">
    <!-- filter -->
    <h2>Filter</h2>
    <div class="content-card content">
    <form method="POST" action="">
    <!-- code du form -->
    </form>
    </div>
    <div id="filter-results">
    </div>
    </div>
    @endsection

    filterResults.blade.php

    @foreach($articles as $article)
    <p>{{ $article->name }}</p>
    @endforeach
    {!! $articles->render() !!}

    JS

    $("#submit-button").click(function(e) {
    e.preventDefault();
    // ajax request (raw mysql request)
    var requestQuery = ...; // (assez long)
    console.log(requestQuery); // Vérification dans la console
    $.ajax({
    headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
    url: '../articles/request/ajax/articles/filter',
    type: 'POST',
    data: {
    request: requestQuery
    },
    success: function(html) {
    //getQuery(page);
    $("#filter-results").empty().html(html);
    }
    });
    });
    $(window).on('hashchange', function() {
    // si il y a un hash dans l'url
    if (window.location.hash) {
    // var $page contient la valeur du hash et supprime le # de l'url
    var page = window.location.hash.replace('#', '');
    // si $page n'est pas un nombre ou si c'est <= 1, ça retourne false
    if (page == Number.NaN || page <= 0) {
    return false;
    }
    // si c'est ok, la fonction getData() est retournée avec $page en paramètre
    else {
    getData(page);
    }
    }
    });

    $(document).on('click', '.pagination a', function(e) {
    e.preventDefault();
    $('.pagination li').removeClass('active');
    $(this).parent('li').addClass('active');
    var url = $(this).attr('href');
    var page = $(this).attr('href').split('page=')[1];
    getData(page,url);
    });

    function getData(page,url) {
    $.ajax(
    {
    url: url,
    type: 'get',
    datatype: 'html',
    done: function(data) {
    console.log('ok');
    $('#filter-results').empty().html(data);
    location.hash = page;
    },
    fail: function(jqXHR, ajaxOptions, thrownError) {
    console.log('No response from server');
    }
    });
    }

    Je vous remercie d'avance,
    Thomas

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    1998

    Salut,

    Il me semble qu'il faut générer la vue avec render :

    return view('filterResults', compact('articles'))->render();
  • Avatar de ThomasHabets
    Membre depuis :
    14/07/2018
    Messages :
    8

    Bonjour et merci pour votre réponse rapide.
    En fait je retourne la variable $html dans laquelle est stockée la vue. La variable est ensuite passée à ajax dans la function success(). Cela fonctionne sans le render() puisque filtery() est déjà utilisé pour rendre la vue lorsque l'utilisateur valide le formulaire.
    C'est uniquement la pagination qui ne fonctionne pas.

    (Pour en avoir le coeur net, j'ai tout de même testé avec render() mais le problème persiste.)

    Merci et bonne soirée

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    1998

    Ca génère quoi au niveau des liens de pagination ?

  • Avatar de ThomasHabets
    Membre depuis :
    14/07/2018
    Messages :
    8

    J'obtiens quelque chose de cette forme:

    <ul class="pagination" role="navigation">
    <li>...</li>
    <li>...</li>
    <!-- bouton d'accès à la page 2 dans la pagination -->
    <li class="page-item">
    <a class="page-link" href="domaine/public/articles/request/ajax/articles/filter?page=2">2</a>
    </li>
    </ul>

    Bien sûr, l'attribut href a été raccourci avec "domain" mais l'url prend une bonne forme.

  • Avatar de bestmomo
    Membre depuis :
    07/04/2013
    Messages :
    1998

    Oui mais quand tu cliques sur un lien de pagination tu es plus en Ajax et tu renvoies rien...

  • Avatar de ThomasHabets
    Membre depuis :
    14/07/2018
    Messages :
    8

    Le lien de pagination est cependant actif lorsque l'on clique sur le lien en jQuery, donc la requête devrait être appelée, non ?

  • Avatar de bdfi
    Membre depuis :
    02/03/2014
    Messages :
    69

    Hello ThomasHabets,
    N'est-ce pas une version ancienne de jQuery ? Je n'ai pas été vérifier les paramètres mais ce qui est sur c'est qu'avant une certaine version (1.8 ?) le ".on" ne fonctionnait que pour les liens pré-existants, pas pour des liens ajoutés ensuite dynamiquement. Pour que ça fonctionne pour tous les liens, il fallait utiliser ".live".
    C'est maintenant obsolète, le ".live" est devenu deprecated, il suffit d'utiliser ".on", qui permet d'utiliser les deux modes (seulement les liens pré-existants, ou également les futurs), selon la formulation qu'on applique. Pour un ($element).on("click", data..., l'action s'appliquera sur des nouveaux sous-éléments data dans $element, mais pas à de nouveaux éléments de type $element (notion de delegated events). Puisque ton ".on" s'applique sur tout le document, je ne vois pas pourquoi ça ne fonctionnerait pas, sauf si ton jquery est ancien.
    PS : Il faut quand même bien s'assurer que les insertions de codes scripts (locaux ou fichier externe) se situent bien après les élements auxquels il s'appliquent / aprçs qu'ils soient chargés. Vérifierquand même que ce que je dis s'applique à "document", pas sur... Peut-être vaudrait-il mieux le mettre sur l'élement container par exemple.

Vous ne pouvez pas répondre à ce sujet.