import { ChangeDetectionStrategy, Component, EventEmitter, Input, OnDestroy, OnInit, Output, ViewEncapsulation } from '@angular/core' import { ActivatedRoute, Router } from '@angular/router'; import { isNumeric } from "rxjs/util/isNumeric"; import 'rxjs/add/operator/switchMap'; import { Observable } from "rxjs"; // It is necessary to use ng2-pagination import { DEFAULT_TEMPLATE, DEFAULT_STYLES } from 'ng2-pagination/dist/template'; import { HostWindowService } from "../host-window.service"; import { HostWindowState } from "../host-window.reducer"; import { PaginationOptions } from '../../core/cache/models/pagination-options.model'; /** * The default pagination controls component. */ @Component({ exportAs: 'paginationComponent', selector: 'ds-pagination', templateUrl: 'pagination.component.html', changeDetection: ChangeDetectionStrategy.Default, encapsulation: ViewEncapsulation.Emulated }) export class PaginationComponent implements OnDestroy, OnInit { /** * Number of items in collection. */ @Input() collectionSize: number; /** * Configuration for the NgbPagination component. */ @Input() paginationOptions: PaginationOptions; /** * An event fired when the page is changed. * Event's payload equals to the newly selected page. */ @Output() pageChange: EventEmitter = new EventEmitter(); /** * An event fired when the page size is changed. * Event's payload equals to the newly selected page size. */ @Output() pageSizeChange: EventEmitter = new EventEmitter(); /** * Current page. */ public currentPage = 1; public currentQueryParams = {}; /** * An observable of HostWindowState type */ public hostWindow: Observable; /** * ID for the pagination instance. Only useful if you wish to * have more than once instance at a time in a given component. */ private id: string; /** * A boolean that indicate if is an extra small devices viewport. */ public isXs: boolean; /** * Number of items per page. */ public pageSize: number = 10; /** * A number array that represents options for a context pagination limit. */ private pageSizeOptions: Array; /** * Local variable, which can be used in the template to access the paginate controls ngbDropdown methods and properties */ public paginationControls; /** * Subscriber to observable. */ private routeSubscription: any; /** * An object that represents pagination details of the current viewed page */ public showingDetail: any = { range: null, total: null }; /** * Subscriber to observable. */ private stateSubscription: any; /** * Method provided by Angular. Invoked after the constructor. */ ngOnInit() { this.stateSubscription = this.hostWindowService.isXs() .subscribe((status: boolean) => { this.isXs = status; }); this.checkConfig(this.paginationOptions); this.id = this.paginationOptions.id || null; this.currentPage = this.paginationOptions.currentPage; this.pageSize = this.paginationOptions.pageSize; this.pageSizeOptions = this.paginationOptions.pageSizeOptions; this.routeSubscription = this.route.queryParams .map(queryParams => queryParams) .subscribe(queryParams => { this.currentQueryParams = queryParams; if(this.id == queryParams['pageId'] && (this.paginationOptions.currentPage != queryParams['page'] || this.paginationOptions.pageSize != queryParams['pageSize']) ) { this.validateParams(queryParams['page'], queryParams['pageSize']); } }); this.setShowingDetail(); } /** * Method provided by Angular. Invoked when the instance is destroyed. */ ngOnDestroy() { this.stateSubscription.unsubscribe(); this.routeSubscription.unsubscribe(); } /** * @param route * Route is a singleton service provided by Angular. * @param router * Router is a singleton service provided by Angular. */ constructor( private route: ActivatedRoute, private router: Router, public hostWindowService: HostWindowService ){ } /** * Method to set set new page and update route parameters * * @param page * The page being navigated to. */ public doPageChange(page: number) { this.router.navigate([], { queryParams: Object.assign({}, this.currentQueryParams, { pageId: this.id, page: page, pageSize: this.pageSize }) }); this.currentPage = page; this.setShowingDetail(); this.pageChange.emit(page); } /** * Method to set set new page size and update route parameters * * @param pageSize * The new page size. */ public setPageSize(pageSize: number) { this.router.navigate([], { queryParams: Object.assign({}, this.currentQueryParams, { pageId: this.id, page: this.currentPage, pageSize: pageSize }) }); this.pageSize = pageSize; this.setShowingDetail(); this.pageSizeChange.emit(pageSize); } /** * Method to set pagination details of the current viewed page. */ private setShowingDetail() { let firstItem; let lastItem; let lastPage = Math.round(this.collectionSize / this.pageSize); firstItem = this.pageSize * (this.currentPage - 1) + 1; if (this.currentPage != lastPage) { lastItem = this.pageSize * this.currentPage; } else { lastItem = this.collectionSize; } this.showingDetail = { range: firstItem + ' - ' + lastItem, total: this.collectionSize } } /** * Validate query params * * @param page * The page number to validate * @param pageSize * The page size to validate */ private validateParams(page: any, pageSize: any) { let filteredPageSize = this.pageSizeOptions.find(x => x == pageSize); if (!isNumeric(page) || !filteredPageSize) { let filteredPage = isNumeric(page) ? page : this.currentPage; filteredPageSize = (filteredPageSize) ? filteredPageSize : this.pageSize; this.router.navigate([{ pageId: this.id, page: filteredPage, pageSize: filteredPageSize }]); } else { // (+) converts string to a number this.currentPage = +page; this.pageSize = +pageSize; this.pageChange.emit(this.currentPage); this.pageSizeChange.emit(this.pageSize); } } /** * Ensure options passed contains the required properties. * * @param paginateOptions * The paginate options object. */ private checkConfig(paginateOptions: any) { let required = ['id', 'currentPage', 'pageSize', 'pageSizeOptions']; let missing = required.filter(function (prop) { return !(prop in paginateOptions); }); if (0 < missing.length) { throw new Error("Paginate: Argument is missing the following required properties: " + missing.join(', ')); } } }