DEV Community

Julia Lange for visuellverstehen

Posted on

6 1

How to add pagination to your custom relationship fieldtype in Statamic

Usually when building a custom relationship fieldtype you want to work with data from somewhere else than Statamic.

In this example we extended the relationship fieldtype in order to provide a list of imported tags. Thanks to the Statamic docs, this is pretty easy.



class Tags extends Relationship
{
    protected array | string $tags;

    // Fetch tags from api. 
    // Using a facade makes it nice to read and easier to test.
    public function __construct()
    {
        $this->tags = Api::tags();
    }


    // Define columns.
    protected function getColumns()
    {
        return [
            Column::make('title'),
        ];
    }

    // Take search requests into account. 
    // Just comparing strings. Nothing fancy.
    public function getIndexItems($request)
    {
        return collect($this->tags)
          ->filter(function ($tag) use ($request) {
            if (! $request->search) {
                return true;
            }

            return Str::contains($tag['title'], $request->search);
        });
    }
}


Enter fullscreen mode Exit fullscreen mode

In many cases this would already be it. But what if you have a huge amount of tags or items that need to be loaded into Statamics selector stack?
I found that loading about 16000 tags at once into the selector stack would either cause unbearable loading times or even make the browser freeze.

This issue could be solved by enabling pagination. But unfortunately the relationship fieldtype does not automatically enable pagination when loading a specific number of items.

In order to do so and show pagination at the bottom of the selector stack you need to return an instance of the \Statamic\Extensions\Pagination\LengthAwarePaginator instead of a collection in the getIndexItems method.

This could be done like this:



public function getIndexItems($request)
    {
        $tags = collect($this->tags)->filter(function ($tag) use ($request) {
            if (! $request->search) {
                return true;
            }

            return Str::contains($tag['title'], $request->search);
        });

        return $this->paginate($tags);
    }


    protected function paginate($tags): LengthAwarePaginator
    {
        $currentPage = Paginator::resolveCurrentPage();
        $perPage = 50;
        $total = $tags->count();
        $result = $total ? $tags->forPage($currentPage, $perPage) : collect();

        return new LengthAwarePaginator($result, $total, $perPage, $currentPage, []);
    }


Enter fullscreen mode Exit fullscreen mode

Curios about the LengthAwarePaginator? Read more in the Laravel Docs

Et voilà - a custom relationship fieldtype with added pagination:

A custom relationship fieldtype with added pagination in Statamic

Hostinger image

Get n8n VPS hosting 3x cheaper than a cloud solution

Get fast, easy, secure n8n VPS hosting from $4.99/mo at Hostinger. Automate any workflow using a pre-installed n8n application and no-code customization.

Start now

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay