kevin201's avatar

Best Practice - Next/Previous in list

I have a view with an index list of items, I click on an item in the list to get details of that item.

On the detail view I have "Next Item" and "Previous Item" buttons, to navigate to the next, or previous, item in the list.

I have two controller methods, one to produce the collection of items for the index, and one to produce the details for an item.

The question is: how to get the 'next' and 'previous' items in the detail method without re-querying the database every time, duplicating the query that's just been done in the index method?

Is there a way of 'holding' the collection from the index somehow, and just stepping up and down it?

0 likes
10 replies
Snapey's avatar

There are multiple ways. One common approach is to load all the data and then use a modal to show the detail rather than a full page reload.

kevin201's avatar

@Snapey Thank you. I thought it would be a common requirement. Unfortunately, modals wouldn't suit this particular application, can you point me towards one or two of the other solutions?

newbie360's avatar

@kevin201 In the show route you still need 3 query, one for the current model, and

previous

    ->where('id', '<', $this->id)
    ->orderByDesc('id')
    ->first();

next

    ->where('id', '>', $this->id)
    ->orderBy('id')
    ->first();

and may be you can combine use Cache, cache the list view paginated records ids in asc order, but need to solve the problem when there no cache of the list view page 2

If Filament can use https://filamentphp.com/content/leandrocfe-navigating-filament-pages-with-previous-and-next-buttons

I opened an issues seems no one reply ;(

https://github.com/leandrocfe/article-fi-page-nav/issues/1

Tray2's avatar

@newbie360 This would require that the list is sorted by the id from the beginning, I would go with @snapey sollution instead.

newbie360's avatar

@Tray2 Yep, i know that, but if the show route has many content, for example that page included all the relation data, so the page is very long, if use modal in the list view is not good

kevin201's avatar

@newbie360 Thanks. That's exactly what I have currently. I was wondering if maybe I could somehow cache the unpaginated index collection and query that instead of the db.

newbie360's avatar

@kevin201 For me, two more query in the show route is fine.

Otherwise you need a lot code to handle the cache, what happen created or deleted a record, you need re-cache every things

martinbean's avatar

The question is: how to get the 'next' and 'previous' items in the detail method without re-querying the database every time, duplicating the query that's just been done in the index method?

@kevin201 Getting the “next“ and “previous” item is not the same query as fetching a paginated list of ~15 records.

Your application isn’t going to blow up by doing a query to retrieve the previous and next items for the current item:

public function show(Post $post)
{
    $previous = Post::query()
        ->where('published_at', '<', $post->published_at)
        ->orderByDesc('published_at')
        ->first();

    $next = Post::query()
        ->where('published_at', '>', $post->published_at)
        ->orderBy('published_at')
        ->first();

    return view('post.show')->with([
        'post' => $post,
        'previous' => $previous,
        'next' => $next,
    ]);
}
<!-- resources/views/post/show.blade.php -->
<article>
    <!--
        TODO: Put main post mark-up here
    -->
</article>
@if($previous || $next)
    <ul>
        @if($previous)
            <li>
                <span>{{ __('Previous:') }}</span>
                <a href="{{ $previous->url() }}" rel="prev">{{ $previous->headline }}</a>
            </li>
        @endif
        @if($next)
            <li>
                <span>{{ __('Next:') }}</span>
                <a href="{{ $next->url() }}" rel="next">{{ $next->headline }}</a>
            </li>
        @endif
    </ul>
@endif
Snapey's avatar

If you only want 1 record at a time then thats the same as ->paginate(1)

kevin201's avatar

@Snapey Thanks. Yes, the one record simple pagination would be great if I could find a way to 'jump in' to the list from the index at the right spot.

Many thanks to everyone for their answers.

Please or to participate in this conversation.