私は/list/students?page=5&rows=10
のようなAPIエンドポイントにページネーションパラメータpage
とsize
を指定しています。 angular2ページネーションコンポーネントを作成したいのですが。
入力パラメータは
また、矢印ボタンで特定のページやサイズに移動したい。
このコンポーネントを実装するにはどうすればよいですか?
以下のコードとサービスを使用してページングコンポーネントを作成できます
app.component.html
<paging-component
[TotalItems]="pagination.TotalItems"
[CurrentPage]="pagination.CurrentPage"
[PageSize]="pagination.PageSize"
[TotalPageLinkButtons]="pagination.TotalPageLinkButtons"
[RowsPerPageOptions]="pagination.RowsPerPageOptions"
(onPageChange)="myChanges($event)"></paging-component>
app.component.tsは以下のとおりです。
import {Component} from '@angular/core';
@Component({
selector : 'app-root',
templateUrl: './app.component.html',
styleUrls : ['./app.component.css']
})
export class AppComponent {
pagination = {
TotalItems: 100,
CurrentPage: 1,
PageSize: 10,
TotalPageLinkButtons: 5,
RowsPerPageOptions: [10, 20, 30, 50, 100]
};
/* Paging Component metod */
myChanges(event) {
this.pagination.CurrentPage = event.currentPage;
this.pagination.TotalItems = event.totalItems;
this.pagination.PageSize = event.pageSize;
this.pagination.TotalPageLinkButtons = event.totalPageLinkButtons;
}
}
app.component.module
import {BrowserModule} from '@angular/platform-browser';
import {NgModule} from '@angular/core';
import {FormsModule} from '@angular/forms';
import {HttpModule} from '@angular/http';
import {AppComponent} from './app.component';
import {PagingComponent} from './components/paging-component/paging-component.component';
import {PagingService} from './service/paging-service.service';
@NgModule({
declarations: [
AppComponent,
PagingComponent
],
imports: [
BrowserModule,
FormsModule,
HttpModule
],
providers: [ PagingService],
bootstrap: [AppComponent]
})
export class AppModule { }
paging-service.service.tsは
import { Injectable } from '@angular/core';
@Injectable()
export class PagingService {
/**
* @param totalItems : Total items to be listed
* @param currentPage : Current page number ( Pages starting from 1 not 0)
* @param pageSize : The number of items in the page
* @param totalPageLinkButtons : The number of total page link buttons
* @returns {{
* startPage: number,
* endPage: number,
* startIndex: number,
* endIndex: number,
* totalPageLinkButtons: number,
* totalItems: number,
* currentPage: number,
* pageSize: number,
* totalPages: number,
* pages: (Observable<number>|any)
* }}
*/
getPagingServiceItems(totalItems: number, currentPage: number = 1, pageSize: number = 10, totalPageLinkButtons: number = 5) {
totalItems = totalItems || 1;
/* if currentPage not exists default value will be '1' */
currentPage = currentPage || 1;
/* The default value of the number of items in the page is 10 if not exist */
pageSize = pageSize || 10;
/* The default value of the number of total page link buttons is 10 if not exist */
totalPageLinkButtons = totalPageLinkButtons || 10;
/* calculate total pages */
const totalPages = Math.ceil(totalItems / pageSize);
let startPage: number; // start Page Button number
let endPage: number; // end Page Button number
if (totalPages <= totalPageLinkButtons) {
// less than totalPageButtons then show all
// 1,2,3,.., totalPages are buttons
startPage = 1;
endPage = totalPages;
} else {
// more than totalPageButtons then calculate start and end pages
// currentPage will be on the center of the paging
if (currentPage <= Math.ceil(totalPageLinkButtons / 2)) {
startPage = 1;
endPage = totalPageLinkButtons;
} else if (currentPage + Math.ceil(totalPageLinkButtons / 2) > totalPages) {
startPage = totalPages - totalPageLinkButtons + 1;
endPage = totalPages;
} else {
startPage = currentPage - Math.ceil(totalPageLinkButtons / 2) + 1;
endPage = startPage + totalPageLinkButtons - 1;
}
}
// calculate start and end item indexes
// Indexes are started from 0 ! It is important
const startIndex = (currentPage - 1) * pageSize;
const endIndex = Math.min(startIndex + pageSize - 1, totalItems - 1);
const pages = [];
// create an array of pages to ng-repeat in the pager control
for ( let i = startPage; i <= endPage ; i++) {
pages.Push(i);
}
// return object with all paging properties required by the view
return {
startPage : startPage,
endPage : endPage,
startIndex : startIndex,
endIndex : endIndex,
totalPageLinkButtons: totalPageLinkButtons,
totalItems : totalItems,
currentPage : currentPage,
pageSize : pageSize,
totalPages : totalPages,
pages : pages
};
}
}
独自のページネーションコンポーネントを簡単に作成できます。
プロジェクトでAngular CLIを使用する場合は、ng g c pagination
を使用してアプリフォルダーに新しいコンポーネントを作成できます。AngualrCLIを使用しない場合は、フォルダーのページネーションと次のファイルを作成します。
pagination.ts
export class Page {
page: number;
itemsPerPage: number;
}
pagination.component.ts
import { Component, EventEmitter, Input, OnInit, Output } from '@angular/core';
import { Page } from './pagination';
@Component({
selector: 'app-pagination',
templateUrl: './pagination.component.html',
styleUrls: ['./pagination.component.css']
})
export class PaginationComponent implements OnInit {
@Input() maxPages: number;
@Input() current: number;
@Input() postsPerPage: number[];
@Input() itemsPerPage: number;
@Output() changePage = new EventEmitter();
pages: any[] = [];
pageModel: Page = {
page: this.current,
itemsPerPage: this.itemsPerPage
};
constructor() { }
ngOnInit() {
if (this.maxPages) {
this.createPages();
}
}
setPage(page: number, perPage: number) {
this.pageModel.page = page;
this.pageModel.itemsPerPage = perPage;
this.changePage.emit(this.pageModel);
}
createPages() {
for(let i=1; i <= this.maxPages; i++) {
this.pages.Push(i);
}
}
}
pagination.component.html
私自身のプロジェクトではbootstrapを使用していますが、このテンプレートを簡単にカスタマイズできます。
<div class="row">
<div class="col-lg-6">
<nav aria-label="Pagination" *ngIf="maxPages > 1">
<ul class="pagination">
<li [class.disabled]="current == 1">
<a href="javascript:;"
(click)="setPage(current-1, itemsPerPage)"
aria-label="Previous">
<span aria-hidden="true">«</span>
</a>
</li>
<li *ngFor="let page of pages;" [class.active]="page == current">
<a href="javascript:;" (click)="setPage(page, itemsPerPage)">{{ page }}</a>
</li>
<li [class.disabled]="current == maxPages">
<a href="javascript:;" (click)="setPage(current+1 ,itemsPerPage)" aria-label="Next">
<span aria-hidden="true">»</span>
</a>
</li>
</ul>
</nav>
</div>
<div class="col-lg-6 text-right per-page">
<nav aria-label="Anzahl der Beiträge pro Seite">
<p>Anzahl der Beiträge pro Seite:</p>
<ul class="pagination">
<li *ngFor="let perPage of postsPerPage;" [class.active]="perPage == itemsPerPage">
<a href="javascript:;" (click)="setPage(current, perPage)">{{ perPage }}</a>
</li>
</ul>
</nav>
</div>
</div>
pagination.component.css
ここにいくつかのスタイルがあります。
.per-page nav p {
display: inline-block;
margin: 25px 10px;
font-weight: bold;
padding: 2px 0;
}
.per-page nav .pagination {
float: right;
}
このファイルを作成したら、このコンポーネントをapp.module.ts
にインポートする必要があります。
エンドポイントのようなAPIでこのページネーションを使用する例を次に示します。
students-list.component.html
テンプレートにページ分割コンポーネントを配置し、これから放出されるevetを取得します。また、いくつかのデータを入力を介してページネーションコンポーネントに送信する必要があります。
<app-pagination [maxPages]="maxPages"
[current]="currentPage"
[postsPerPage]="postsPerPage"
[itemsPerPage]="itemsPerPage"
(changePage)="pageChanged($event)"></app-pagination>
students-list.component.ts
では、いくつかのデフォルト値を定義する必要があり、発行されたイベントを処理できます。
students-list.component.ts
itemsPerPage: number = 25;
postsPerPage: number[] = [25, 50, 100];
constructor(private studentService: StudentService) {}
pageChanged(event) {
this.page = event.page;
this.itemsPerPage = event.itemsPerPage
this.loadStudentsByPage(this.page, this.itemsPerPage);
}
loadStudentsByPage(page: number, rows: number) {
let params = new URLSearchParams();
params.set('page', page.toString());
params.set('rows', rows.toString());
this.isLoading = true;
this.studentService.getStudentListByParams(params).subscribe(data => {
this.students= data;
this.isLoading = false;
}, error => {
this.isLoading = false;
console.log(error);
});
}
students-list.service.ts
APIから学生を取得するためのサービス関数の例を次に示します。
headers = new Headers({'Content-Type': 'application/json', 'Accept': 'application/json'});
getStudentListByParams(params: URLSearchParams): Observable<StudentsModel> {
const endpoint = domain + '/list/students';
return this.http
.get(endpoint, { search: params, headers: this.headers })
.map((res: Response) => res.json())
.catch((e) => this.handleError(e));
}
この例を使用していただければ、理解しやすくなります。