DEMOS / Pagination

Live Pagination

Combine Pagination with LiveComponent for reactive filters and page changes. Each control remains an ordinary link, and changing a filter returns you to the first page.

ux.symfony.com

The paginator still exposes totals, ranges, and generated URLs to Twig.

A filterable catalog

color and pattern are URL-bound LiveProps. The component receives its repository through ordinary Symfony dependency injection.

createPagination() starts from the filtered repository query, preserves the active filters in generated URLs, and asks for 10 jerseys at a time.

30#[LiveProp(url: true)]
31public string $color = '';
32
33#[LiveProp(url: true)]
34public string $pattern = '';
35
36public function __construct(
37    private readonly PaginatorInterface $paginator,
38    private readonly JerseyRepository $jerseys,
39) {
40}
41
42protected function createPagination(): PaginationBuilder
43{
44    return $this->paginator
45        ->query($this->jerseys->find($this->color, $this->pattern))
46        ->queryParameters(array_filter([
47            'color' => $this->color,
48            'pattern' => $this->pattern,
49        ]))
50        ->perPage(10)
51        ->sliding(5);
52}

Add the pagination trait

ComponentWithPaginationTrait adds the writable page state and the actions that move forward, backward, or to a specific page.

The component does not need to implement that state or duplicate the navigation logic itself.

// ... use statements hidden - click to show
20use Symfony\UX\Pagination\LiveComponent\ComponentWithPaginationTrait;
21use Symfony\UX\Pagination\PaginationBuilder;
22use Symfony\UX\Pagination\PaginatorInterface;
20
21#[AsLiveComponent('LivePagination')]
22final class LivePagination
23{
24    use ComponentWithPaginationTrait;
25    use DefaultActionTrait;

Reset after a filter changes

toggleFilter() validates the selected option and updates the corresponding LiveProp before the component renders the filtered query again.

resetPage() returns to page 1 first. A smaller filtered result can never leave the component stranded on a page that no longer exists.

68#[LiveAction]
69    public function toggleFilter(
70        #[LiveArg] string $name,
71        #[LiveArg] string $value,
72    ): void {
73        $choices = $this->getFilters()[$name] ?? null;
74        if (
75            null === $choices
76            || !\array_key_exists($value, $choices)
77        ) {
78            return;
79        }
80
81        $selection = $value === match ($name) {
82            'color' => $this->color,
83            'pattern' => $this->pattern,
84            default => null,
85        } ? '' : $value;
86
87        match ($name) {
88            'color' => $this->color = $selection,
89            'pattern' => $this->pattern = $selection,
90            default => null,
91        };
92
93        $this->resetPage();
94    }
95}

ux_pagination() still renders real links. paginationLinkAttributes adds the Live action that updates only this component when JavaScript is available.

The same markup keeps its normal navigation fallback, and the selected theme does not need any LiveComponent-specific code.

{{ ux_pagination(
    this.pagination,
    show_info: false,
    link_attributes: this.paginationLinkAttributes,
    theme: 'components/LivePagination/Theme.html.twig',
) }}
Author smnandre
Published 2026-08-04