Skip to content

Instantly share code, notes, and snippets.

@y-takagi
Last active January 19, 2023 16:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save y-takagi/f09e05141ffa7ca38cd0018319455dd6 to your computer and use it in GitHub Desktop.
Save y-takagi/f09e05141ffa7ca38cd0018319455dd6 to your computer and use it in GitHub Desktop.
GoogleのPaginationっぽいやつ

GoogleのPaginationっぽいやつ

Tech Stack

  • Angular
  • Angular Material
  • Tailwindcss
<ng-container *ngIf="state$ | async as state">
<div class="flex items-start gap-2">
<button [class.invisible]="!state.hasPrev" (click)="onNavigate(state.page - 1)">
<mat-icon>navigate_before</mat-icon>
</button>
<ng-container *ngFor="let page of state.pages">
<ng-container *ngIf="page === state.page; else otherPage">
<div class="w-6 text-center">{{ page }}</div>
</ng-container>
<ng-template #otherPage>
<button class="tw-w-6 text-gray" (click)="onNavigate(page)">{{ page }}</button>
</ng-template>
</ng-container>
<button [class.invisible]="!state.hasNext" (click)="onNavigate(state.page + 1)">
<mat-icon>navigate_next</mat-icon>
</button>
</div>
</ng-container>
export interface Pagination {
total: number
page: number;
limit: number;
hasPrev: boolean;
hasNext: boolean;
}
@Component({
selector: 'app-paginator',
templateUrl: './paginator.component.html',
})
export class PaginatorComponent {
private readonly pagination$$ = new BehaviorSubject<{ page: number; pages: number[]; hasPrev: boolean; hasNext: boolean } | null>(null);
readonly state$ = this.pagination$$.asObservable();
@Input() maxPage = 10;
@Input()
set pagination(value: Pagination | undefined) {
if (value == null) return;
this.pagination$$.next({
page: value.page,
pages: this.generatePages(value),
hasPrev: value.hasPrev,
hasNext: value.hasNext
});
}
@Output() navigate = new EventEmitter<number>();
onNavigate(page: number): void {
this.navigate.emit(page);
}
private generatePages(value: Pagination) {
const totalPage = Math.ceil(value.total / value.limit);
if (totalPage <= this.maxPage) return this.range(totalPage);
if (value.page <= Math.floor(this.maxPage / 2) + 1) {
return this.range(this.maxPage);
} else if (value.page >= totalPage - (Math.floor(this.maxPage / 2) - 1)) {
return this.range(this.maxPage, totalPage - this.maxPage + 1);
} else {
return this.range(this.maxPage, value.page - Math.ceil(this.maxPage / 2));
}
}
private range(size: number, startAt: number = 1) {
return [...Array(size).keys()].map((i) => i + startAt);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment