web-dev-qa-db-fra.com

Select2 v4 comment paginer les résultats en utilisant AJAX

J'essaie de paginer les résultats (toutes les 25 lignes) en utilisant Select2 4.0, mais je ne sais pas comment y parvenir. Quelqu'un sait-il comment le faire?

Si l'utilisateur atteint la fin des 25 lignes et s'il y a plus de lignes, je voudrais le charger et l'afficher.

Voici mon modèle HTML

<div class="form-group">
    {!! Form::select('breed_id', $breeds, null, ['class' => 'form-control', 'id' =>'breed_id'] ) !!}
</div>

Et voici le JavaScript pour Select2.

$("#breed_id").select2({
    placeholder: 'Breed...',
    width: '350px',
    allowClear: true,
    ajax: {
        url: '',
        dataType: 'json',
        data: function(params) {
            return {
                term: params.term
            }
        },
        processResults: function (data, page) {
            return {
                results: data
            };
        },
        cache: true
    }
});

Et c'est le code que j'ai pour mon contrôleur

if ($request->ajax())
{
    $breeds = Breed::where('name', 'LIKE',  '%' . Input::get("term"). '%')->orderBy('name')->take(25)->get(['id',DB::raw('name as text')]);

    return response()->json($breeds);
}

Aussi quand j'ai essayé de mettre params.page il dit "non défini".

19
Diego

Select2 prend en charge la pagination lors de l'utilisation de données distantes via la touche pagination qui provient de processResults.

Pour un défilement infini, l'objet pagination devrait avoir une propriété more qui est un booléen (true ou false). Cela indiquera à Select2 s'il doit charger plus de résultats lorsqu'il atteint le bas ou s'il a atteint la fin des résultats.

{
  results: [array, of, results],
  pagination: {
    more: true
  }
}

Dans votre cas, vous avez la possibilité de façonner vos résultats. Vous pouvez donc réellement modifier votre réponse JSON pour qu'elle corresponde au format attendu, ce qui signifie que vous n'aurez même pas besoin d'utiliser processResults.

Select2 peut transmettre le numéro de page en tant que page si vous modifiez la fonction ajax.data Pour le renvoyer.

data: function(params) {
    return {
        term: params.term || "",
        page: params.page || 1
    }
},

Et puis vous pourrez obtenir la page en utilisant Input::get('page'). Et vous pouvez calculer le nombre total de résultats à ignorer en utilisant (page - 1) * resultCount, Où resultCount est 25 Dans votre cas. Cela vous permettra de modifier votre requête pour combiner LIMIT et OFFSET pour obtenir exactement les résultats dont vous avez besoin.

$page = Input::get('page');
$resultCount = 25;

$offset = ($page - 1) * $resultCount;

Et vous pouvez utiliser la requête suivante pour générer une requête LIMIT/OFFSET (basée sur cette question de débordement de pile .

$breeds = Breed::where('name', 'LIKE',  '%' . Input::get("term"). '%')->orderBy('name')->skip($offset)->take($resultCount)->get(['id',DB::raw('name as text')]);

Donc maintenant $breeds Ne contiendra que les résultats demandés. La seule chose qui reste à faire est de façonner la réponse pour qu'elle corresponde à la manière dont Select2 l'attend. Vous pouvez déterminer s'il y a plus de pages en vérifiant le nombre total de résultats et en vérifiant si vous avez dépassé la limite.

$count = Breed::count();
$endCount = $offset + $resultCount;
$morePages = $endCount > $count;

Alors maintenant, $morePages Devrait être un booléen, c'est exactement ce que Select2 recherche dans pagination.more. Maintenant, vous avez juste besoin de façonner la réponse pour qu'elle corresponde au format que j'ai mentionné plus tôt.

$results = array(
  "results" => $breeds,
  "pagination" => array(
    "more" => $morePages
  )
);

Et puis rendre cela

return response()->json($results);

Tout mettre ensemble, vous obtenez ceci pour JavaScript

$("#breed_id").select2({
    placeholder: 'Breed...',
    width: '350px',
    allowClear: true,
    ajax: {
        url: '',
        dataType: 'json',
        data: function(params) {
            return {
                term: params.term || '',
                page: params.page || 1
            }
        },
        cache: true
    }
});

Et ce qui suit pour votre contrôleur

if ($request->ajax())
{
    $page = Input::get('page');
    $resultCount = 25;

    $offset = ($page - 1) * $resultCount;

    $breeds = Breed::where('name', 'LIKE',  '%' . Input::get("term"). '%')->orderBy('name')->skip($offset)->take($resultCount)->get(['id',DB::raw('name as text')]);

    $count = Breed::count();
    $endCount = $offset + $resultCount;
    $morePages = $endCount > $count;

    $results = array(
      "results" => $breeds,
      "pagination" => array(
        "more" => $morePages
      )
    );

    return response()->json($results);
}
38
Kevin Brown