13

I am displaying paginated results that I get from Algolia. I have two queries in my controller that I paginate. This is how I send the data from the controller to the view:

public function index(Request $request)
{
    if(!$request->q && !$request->page){
      return redirect('/');
    }

    $videos = Video::search($request->q)->paginate(1);
    $videosCollection = $videos->getCollection();

    return fractal()
      ->collection($videosCollection)
      ->parseIncludes(['player'])
      ->transformWith(new VideoTransformer)
      ->paginateWith(new IlluminatePaginatorAdapter($videos))
      ->toArray();
}

So then when I search for example for 'rene' the result is displayed on url http://videoapp.app/search?q=rene And the data that I get looks like this:

{
  data: [
    {
      id: 46,
      description: null,
      views: 0,
      created_at: "1 month ago",
      player: {
        data: {
          id: 34,
          image: "15889ca47e557c12240142_1013305815416003_5199651181367705874_n.jpg",
          first_name: "Bruno",
          last_name: "Hendricks"
    }
  }
}
],
meta: {
  pagination: {
    total: 2,
    count: 1,
    per_page: 1,
    current_page: 1,
    total_pages: 2,
    links: {
      next: "http://videoapp.app/search?query=rene&page=2"
      }
    }
  }
}

But the pagination link that is being created for the next page is "http://videoapp.app/search?query=rene&page=2" and if I click on it the metadata is changed and I get the results for the whole table and not just for the result of my first query that was 'rene' in this example. If I on the other hand type the url in the browser http://videoapp.app/search?q=rene&page=2 then it works like it should be. How I can change those generated links so that it works as it should be?

I have also tried with another example from SO, which again didn't work for me:

Controller:

    if(!$request->q && !$request->page){
      return redirect('/');
    }

    $players = Player::search($request->q)
                ->paginate(1);

    $videos = Video::search($request->q)
                ->paginate(1);
    $videos->setPageName('videos');

View

{{ $videos->appends(array_except(Request::only('q'), 'page'))->links() }}

and

{{ $players->appends(array_except(Request::only('q'), 'videos'))->links() }}

I have also tried the suggestion from the answers:

public function index(Request $request)
{
    $q = $request->q;
    $videosPage = $request->vpage;
    $playersPage = $request->ppage;

    if (! $request->q) {
        return redirect('/');
    }

    $players = Player::search($q)
        ->paginate(1, 'ppage')
        ->appends(['q' => $q, 'vpage' => $videosPage]);
    $videos = Video::search($q)
        ->paginate(1, 'vpage')
        ->appends(['q' => $q, 'ppage' => $playersPage]);

    return view('search.index', [
        'players' => $players,
        'videos'  => $videos,
    ]);
}

But that also didn't work, when I would click on a link for players it would go back to video results for example. Can't seem to find any solution for this problem?

Leff
  • 1,968
  • 24
  • 97
  • 201

3 Answers3

4

The problem is you need 3 separate query string values ("q" for search term, and the page number of each paginator), and the default pagination links clear them, leaving only the one corresponding to the current paginator.

I would try this:

public function index(Request $request)
{
    $q = $request->q;
    $videosPage = $request->vpage;
    $playersPage = $request->ppage;

    if (! $request->q) {
        return redirect('/');
    }

    $players = Player::search($q)
        ->paginate(1, 'ppage')
        ->appends(['q' => $q, 'vpage' => $videosPage]);
    $videos = Video::search($q)
        ->paginate(1, 'vpage')
        ->appends(['q' => $q, 'ppage' => $playersPage]);

    return view('search.index', [
        'players' => $players,
        'videos'  => $videos,
    ]);
}

This way, each paginator has its own page name, and keeps the other one and the search term in the query string.

alepeino
  • 9,551
  • 3
  • 28
  • 48
  • 1
    It seems to work fine for videos, but when I switch to players tab and start clicking on new pages it goes back to videos tab and video results. – Leff Feb 23 '17 at 18:19
  • @Leff well, clicking on the paginator link will refresh the browser with the response of the new request, so the "active tab state" will not be preserved. It seems like the simplest way would be AJAX requests then... In fact, why don't you use the Algolia javascript client instead? – alepeino Feb 23 '17 at 18:24
  • 1
    I am using Algolia javascript client for autocomplete, not sure how would I use it for this problem. – Leff Feb 23 '17 at 19:40
0
if (!$request->q) {
    return redirect('/');
}

This is causing your problem, when you press the paginate link it will replace ?q=something to ?page=2 which will cause your function to redirect.

Use something else ex:

if(!request->q && !request->page){
    return redirect('/');
}
Marcus
  • 1,850
  • 1
  • 12
  • 24
  • 1
    I don't have any search method in Player model, I am just using the ```Laravel\Scout\Searchable``` in my model for it. – Leff Feb 23 '17 at 09:33
  • and use paginate(1); and not paginate(1, ['*'], 'videos'); – Marcus Feb 23 '17 at 09:51
  • 1
    It is still not working as it should be, the pagination links are created, and there is no error, but I don't get two separate queries, pagination links continue from video results to player results, and I would like to have separate results and paginations in each tab, for players and videos. – Leff Feb 23 '17 at 09:58
  • Now that is a different problem ;) solution to that here: http://stackoverflow.com/questions/24086269/laravel-multiple-pagination-in-one-page – Marcus Feb 23 '17 at 10:05
  • 1
    Yes, and that was my question all along, I saw the solutions from that question, but it didn't help in my case. – Leff Feb 23 '17 at 10:09
  • Should work with his solution, remember to add other_page to your redirect function – Marcus Feb 23 '17 at 10:20
0

Divide the window for players or for videos with <-- - Iframe -- - > or <--- frameset --> Use different method into your controller and output will appear on same window.

Heartbeat
  • 142
  • 9