silverstripe-framework/docs/en/02_Developer_Guides/19_GraphQL/03_working_with_generic_types/05_adding_pagination.md
Aaron Carlino c1cda2b113
WIP: Add new graphql 4 docs (#9652)
* DOCS: Add new graphql 4 docs

* Reorganise docs

* Docs done

* Basic graphql index page

* TOC for getting started

* show folders on graphql index page

* Add middleware note

* Docs update

* Update docs to reflect flushless schema

* Docs updates

* Docs for getByLink

* Query caching docs

* Docs on nested operations

* update docs for new graphql dev admin

* Docs for configurable operations

* Replace readSiteTrees with readPages

* Schema defaults docs

* Docs for inherited plugins

* Docs for customising *

* Docs for field whitelisting

* Change whitelist word

* New docs on modelConfig

* Document dev/build extension

* Document default/global plugins

* Document new input type fields config

* Apply suggestions from code review

Co-authored-by: Andre Kiste <bergice@users.noreply.github.com>

* Note about when procedural schema gets built

* Fix link

* Apply suggestions from code review

Co-authored-by: Andre Kiste <bergice@users.noreply.github.com>

* Apply suggestions from code review

Co-authored-by: Andre Kiste <bergice@users.noreply.github.com>

* DOCS Note about plugins in custom queries

* DOCS Note about filter and custom resolvers

* DOCS Note about canview paging

* DOCS Updated guidance on _extend

See https://github.com/silverstripe/silverstripe-graphql/issues/296

* Apply suggestions from code review

Co-authored-by: Andre Kiste <bergice@users.noreply.github.com>

* DOCS Pre-release warning

Co-authored-by: Ingo Schommer <ingo@silverstripe.com>
Co-authored-by: Andre Kiste <bergice@users.noreply.github.com>
Co-authored-by: Ingo Schommer <me@chillu.com>
2020-10-20 10:56:17 +13:00

3.1 KiB

title summary
Adding pagination Add the pagination plugin to a generic query

Working with generic types

[CHILDREN asList]

[alert] You are viewing docs for a pre-release version of silverstripe/graphql (4.x). Help us improve it by joining #graphql on the Community Slack, and report any issues at github.com/silverstripe/silverstripe-graphql. Docs for the current stable version (3.x) can be found here [/alert]

Adding pagination

We've created a simple generic query for our Country type called readCounties that takes a limit argument.

query {
  readCountries(limit: 5) {
    name
    code
  }
}

Let's take this a step further and paginate it using a plugin.

The "paginate" plugin

Since pagination is a fairly common task, we can take advantage of some reusable code here and just add a generic plugin for paginating.

[notice] If you're paginating a DataList, you might want to consider using models with read operations, which paginate by default using the paginateList plugin. This will work, too, but requires a bit of code. [/notice]

Let's add the plugin to our query:

app/_graphql/schema.yml

  queries:
    readCountries:
      type: '[Country]'
      plugins:
        paginate: {}

Right now the plugin will add the necessary arguments to the query, build and update the return types. But we still need to provide this generic plugin a way of actually limiting the result set, so we need a resolver.

app/_graphql/schema.yml

  queries:
    readCountries:
      type: '[Country]'
      plugins:
        paginate:
          resolver: ['MyProject\Resolvers\Resolver', 'paginateCountries']

Let's write that resolver code now:

public static function paginateCountries(array $context): Closure
{
    $maxLimit = $context['maxLimit'];
    return function (array $countries, array $args) use ($maxLimit) {
        $offset = $args['offset'];
        $limit = $args['limit'];
        $total = count($countries);
        if ($limit > $maxLimit) {
            $limit = $maxLimit;
        }

        $limitedList = array_slice($countries, $offset, $limit);

        return PaginationPlugin::createPaginationResult($total, $limitedList, $limit, $offset);
    };
}

A couple of things are going on here:

  • Notice the new design pattern of a context-aware resolver. Since the plugin be configured with a maxLimit parameter, we need to get this information to the function that is ultimately used in the schema. Therefore, we create a dynamic function in a static method by wrapping it with context. It's kind of like a decorator.

  • As long as we can do the work of counting and limiting the array, the PaginationPlugin can handle the rest. It will reutrn an array including edges, nodes, and pageInfo.

Rebuild the schema, and test it out:

query {
  readCountries(limit:3, offset:4) {
    nodes {
      name
    }
    }
} 

Further reading

[CHILDREN]