🚀 Big News: Socket Acquires Coana to Bring Reachability Analysis to Every Appsec Team.Learn more
Socket
DemoInstallSign in
Socket

ngx-signal-pagination

Package Overview
Dependencies
Maintainers
1
Versions
17
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

ngx-signal-pagination

Pagination for Angular, powered by signals 🚦

0.0.5
latest
Source
npm
Version published
Weekly downloads
26
-69.77%
Maintainers
1
Weekly downloads
 
Created
Source

ngx-signal-pagination

Pagination for Angular, powered by signals 🚦

Features

  • All signals, no RxJS
  • Works with in-memory data as well as fetching data from server on page change
    • With the help of @tanstack/angular-query-experimental
  • Keep it simple by using the predefined template
  • Take control by rolling with your own template
  • Page number is reflected in URL
    • Not using the RouterModule for this as it uses RxJS

Caveats

  • Page number is reflected in URL, but is not unique for all pagination controls. Having multiple pagination controls on one page is not currently supported.

Todos

  • Deploy a live demo site
  • Deploy an example project
  • Add something like 3 default templates
  • Default asynchronous template could use a better loading indicator
  • Improve type-safety with custom template. These let-... are currently of type any.
    <ng-template
      #paginationTemplate
      let-currentPage="currentPage"
    
  • Improve type-safety with asynchronous data retrieval. Your query should return this format for pagination to work:
    this.todoDal
      .getAll(this.pageChanges() ?? this.simpleQueryStringService.getPageFromQueryString() ?? 1)
      .then(res => ({
        pagedData: res.todos,
        currentPage: res.currentPage,
        nrOfPages: res.nrOfPages,
    }));
    
    That's currently not clear, the query parameter now accepts anything defined through injectQuery().
    query = input.required<CreateQueryResult<T, any>>();
    
    Due to angular-query's type narrowing, it's a bit tricky to customize this.

Installation

npm install ngx-signal-pagination

Usage

With in-memory data

First, the TypeScript bits - import the pagination component, define data and define pagination config:

@Component({
    selector: 'omg-awesome',
    imports: [NgxSignalPaginationComponent],
    templateUrl: './awesome.component.html',
})
export class AwesomeComponent {
    shows = [
        { title: 'Game of Thrones', rating: 9.5 },
        { title: 'Black Mirror', rating: 9.5 },
        /* ... */
    ];
    paging: PaginationOptions = { nrOfItemsPerPage: 5 };
}

Then you can either use the default template:

<ngx-signal-pagination [data]="shows" [config]="paging" #pagination />
<ul class="list-[square] ml-4">
    @for (show of pagination.pageData(); track show.title) {
        <li>{{ show.title }} gets a {{ show.rating }}</li>
    }
</ul>

Alternatively, you can roll your own template:

<ngx-signal-pagination [data]="shows" [config]="paging" #paginationCustomTemplate>
    <ng-template
        #paginationTemplate
        let-currentPage="currentPage"
        let-pages="pages"
        let-previous="previous"
        let-next="next"
        let-goTo="goTo"
    >
        <ol class="flex">
            <li class="p-3" (click)="previous()">previous</li>
                @for (page of pages(); track page) {
                    <li class="p-3 border-solid border-amber-300 border-b-2" [class.bg-amber-300]="page === currentPage()" (click)="goTo(page)">
                        {{ page }}
                    </li>
                }
            <li class="p-3" (click)="next()">next</li>
        </ol>
    </ng-template>
</ngx-signal-pagination>
<ul class="list-[square] ml-4">
    @for (show of paginationCustomTemplate.pageData(); track show.title) {
         <li>{{ show.title }} gets a {{ show.rating }}</li>
    }
</ul>

With asynchronous data retrieval

Asynchronous data retrieval works using the @tanstack/angular-query-experimental library. You'll need to define your query, as well as do a bit of page change handling*.

*I've tried exposing a signal from the pagination component, but this signal not always being there due to the rendering lifecycle made this approach quite cumbersome.

First, the TypeScript bits - import the async pagination component, define your and define pagination config:

@Component({
    selector: 'omg-awesome',
    imports: [NgxSignalPaginationAsyncComponent],
    templateUrl: './awesome.component.html',
})
export class AwesomeComponent {
	private todoDal = inject(TodoDal);
	private simpleQueryStringService = inject(SimpleQueryStringService);
    paging: PaginationOptions = { nrOfItemsPerPage: 5 };

    pageChanges = signal<number | null>(null);

    todoQuery = injectQuery(() => ({
        queryKey: ['todos', this.pageChanges() ?? this.simpleQueryStringService.getPageFromQueryString() ?? 1],
        queryFn: () => this.todoDal.getTodos(this.pageChanges() ?? this.simpleQueryStringService.getPageFromQueryString() ?? 1),
        placeholderData: prev => prev,
    }));

    goToPage(p: number) {
        this.pageChanges.set(p);
    }
}

In this scenario, my TodoDal looks like this:

@Injectable({ providedIn: 'root' })
export class TodoDal {
	#todos = [
		'#1 Clean the house',
		'#2 Eat food',
		'#3 Exercise',
		/* ... */
	];

	getTodos(page: number): Promise<{ pagedData: any[], currentPage: number; nrOfPages: number; }> {
		return new Promise(resolve => {
			setTimeout(() => {
				resolve({
					pagedData: this.#todos.slice((page - 1) * 5, page * 5),
					currentPage: page,
					nrOfPages: Math.ceil(this.#todos.length / 5),
				});
			}, 2000);
		});
	}
}

Then you can either use the default template:

<ngx-signal-async-pagination [query]="todoQuery" (pageChange)="goToPage($event)" [config]="paging" #asyncPagination />
<ul class="list-[square] ml-4">
    @for (todo of asyncPagination.pageData(); track todo) {
        <li>{{ todo }}</li>
    }
</ul>

Or roll a custom template as with the in-memory variant.

Keywords

angular

FAQs

Package last updated on 17 May 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts