There are some examples on drupal.org of adding a pager to the page, if you want to use the one that core uses:
https://api.drupal.org/api/drupal/core%21includes%21pager.inc/function/pager_default_initialize/8.2.x
The second example should work for you:
$page = pager_find_page();
$num_per_page = \Drupal::config('mymodule.settings')->get('num_per_page');
$offset = $num_per_page * $page;
$result = mymodule_remote_search($keywords, $offset, $num_per_page);
// Now that we have the total number of results, initialize the pager.
pager_default_initialize($result->total, $num_per_page);
// Create a render array with the search results.
$render = [];
$render[] = [
'#theme' => 'search_results',
'#results' => $result->data,
'#type' => 'remote',
];
// Finally, add the pager to the render array, and return.
$render[] = ['#type' => 'pager'];
return $render;
I have done this before in my own wired up search pages, it should solve your issue.
You can replace $num_per_page above with 10, if you do not have a custom module to store the setting.
You could go further, and in your code create a service that handles just attaching the pager. I was doing some sandboxing exploring the search API, and came up with this. First, you need to define your service and inject it to your controller (I refer to mine as pager_service).
/**
* @var \Drupal\velirsearch\Service\PagerService
*/
private $pager_service;
/**
* SearchResults constructor.
* @param \Drupal\velirsearch\Service\PagerService $pager_service
*/
public function __construct(PagerService $pager_service) {
$this->pager_service = $pager_service;
}
/**
* @param \Symfony\Component\DependencyInjection\ContainerInterface $container
* @return static
*/
public static function create(ContainerInterface $container) {
$pager_service = $container->get('velirsearch.pager_service');
return new static($pager_service);
}
Then, a method that attaches a pager:
/**
* Convenient method to obtain a pager to attach from the pager service.
* @param $totalRows
* @param $limit
* @return array
*/
protected function attachPager($totalRows, $limit) {
return $this->pager_service->getPager($totalRows, $limit);
}
Then, the service:
namespace Drupal\velirsearch\Service;
use Symfony\Component\DependencyInjection\ContainerAwareTrait;
use Symfony\Component\DependencyInjection\ContainerAwareInterface;
use Symfony\Component\HttpFoundation\RequestStack;
class PagerService implements ContainerAwareInterface {
use ContainerAwareTrait;
/**
* @var \Symfony\Component\HttpFoundation\Request
*/
private $requestStack;
/**
* PagerService constructor.
* @param \Symfony\Component\HttpFoundation\RequestStack $requestStack
*/
public function __construct(RequestStack $requestStack) {
$this->requestStack = $requestStack;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container) {
$requestStack = $container->get('request_stack');
return new static($requestStack);
}
/**
* @param $totalRows
* @param $limit
* @return array
*/
public function getPager($totalRows, $limit = 10) {
pager_default_initialize($totalRows, $limit);
return ['#type' => 'pager'];
}
}
Then, when you need it...
$render[] = $this->attachPager($results->getResultCount(), 10);
return $render;
You don't necessarily have to go that far, I was just looking for ways to reduce the code needed to attach a pager to different instances of search result controllers. YMMV.
Note that I did not use the third argument to pager_default_initialize, $element
, which you will need if your page will have multiple pagers on it.
getResultCount()
, by the way, is a method provided from Search API ResultSet class.
edit: now looking at my answer, your pager service does not need to inject the RequestStack at all. I was probably thinking of another idea and never finished it or figured I did not need it.