paginator.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464
  1. /**
  2. * @license
  3. * Copyright Google LLC All Rights Reserved.
  4. *
  5. * Use of this source code is governed by an MIT-style license that can be
  6. * found in the LICENSE file at https://angular.io/license
  7. */
  8. import { Injectable, Optional, SkipSelf, NgModule, ChangeDetectionStrategy, ChangeDetectorRef, Component, EventEmitter, Input, Output, ViewEncapsulation, ɵɵdefineInjectable } from '@angular/core';
  9. import { Subject } from 'rxjs';
  10. import { coerceNumberProperty, coerceBooleanProperty } from '@angular/cdk/coercion';
  11. import { mixinInitialized, mixinDisabled } from '@angular/material/core';
  12. import { CommonModule } from '@angular/common';
  13. import { MatButtonModule } from '@angular/material/button';
  14. import { MatSelectModule } from '@angular/material/select';
  15. import { MatTooltipModule } from '@angular/material/tooltip';
  16. /**
  17. * @fileoverview added by tsickle
  18. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  19. */
  20. /**
  21. * To modify the labels and text displayed, create a new instance of MatPaginatorIntl and
  22. * include it in a custom provider
  23. */
  24. class MatPaginatorIntl {
  25. constructor() {
  26. /**
  27. * Stream to emit from when labels are changed. Use this to notify components when the labels have
  28. * changed after initialization.
  29. */
  30. this.changes = new Subject();
  31. /**
  32. * A label for the page size selector.
  33. */
  34. this.itemsPerPageLabel = 'Items per page:';
  35. /**
  36. * A label for the button that increments the current page.
  37. */
  38. this.nextPageLabel = 'Next page';
  39. /**
  40. * A label for the button that decrements the current page.
  41. */
  42. this.previousPageLabel = 'Previous page';
  43. /**
  44. * A label for the button that moves to the first page.
  45. */
  46. this.firstPageLabel = 'First page';
  47. /**
  48. * A label for the button that moves to the last page.
  49. */
  50. this.lastPageLabel = 'Last page';
  51. /**
  52. * A label for the range of items within the current page and the length of the whole list.
  53. */
  54. this.getRangeLabel = (/**
  55. * @param {?} page
  56. * @param {?} pageSize
  57. * @param {?} length
  58. * @return {?}
  59. */
  60. (page, pageSize, length) => {
  61. if (length == 0 || pageSize == 0) {
  62. return `0 of ${length}`;
  63. }
  64. length = Math.max(length, 0);
  65. /** @type {?} */
  66. const startIndex = page * pageSize;
  67. // If the start index exceeds the list length, do not try and fix the end index to the end.
  68. /** @type {?} */
  69. const endIndex = startIndex < length ?
  70. Math.min(startIndex + pageSize, length) :
  71. startIndex + pageSize;
  72. return `${startIndex + 1} - ${endIndex} of ${length}`;
  73. });
  74. }
  75. }
  76. MatPaginatorIntl.decorators = [
  77. { type: Injectable, args: [{ providedIn: 'root' },] },
  78. ];
  79. /** @nocollapse */ MatPaginatorIntl.ngInjectableDef = ɵɵdefineInjectable({ factory: function MatPaginatorIntl_Factory() { return new MatPaginatorIntl(); }, token: MatPaginatorIntl, providedIn: "root" });
  80. /**
  81. * \@docs-private
  82. * @param {?} parentIntl
  83. * @return {?}
  84. */
  85. function MAT_PAGINATOR_INTL_PROVIDER_FACTORY(parentIntl) {
  86. return parentIntl || new MatPaginatorIntl();
  87. }
  88. /**
  89. * \@docs-private
  90. * @type {?}
  91. */
  92. const MAT_PAGINATOR_INTL_PROVIDER = {
  93. // If there is already an MatPaginatorIntl available, use that. Otherwise, provide a new one.
  94. provide: MatPaginatorIntl,
  95. deps: [[new Optional(), new SkipSelf(), MatPaginatorIntl]],
  96. useFactory: MAT_PAGINATOR_INTL_PROVIDER_FACTORY
  97. };
  98. /**
  99. * @fileoverview added by tsickle
  100. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  101. */
  102. /**
  103. * The default page size if there is no page size and there are no provided page size options.
  104. * @type {?}
  105. */
  106. const DEFAULT_PAGE_SIZE = 50;
  107. /**
  108. * Change event object that is emitted when the user selects a
  109. * different page size or navigates to another page.
  110. */
  111. class PageEvent {
  112. }
  113. // Boilerplate for applying mixins to MatPaginator.
  114. /**
  115. * \@docs-private
  116. */
  117. class MatPaginatorBase {
  118. }
  119. /** @type {?} */
  120. const _MatPaginatorBase = mixinDisabled(mixinInitialized(MatPaginatorBase));
  121. /**
  122. * Component to provide navigation between paged information. Displays the size of the current
  123. * page, user-selectable options to change that size, what items are being shown, and
  124. * navigational button to go to the previous or next page.
  125. */
  126. class MatPaginator extends _MatPaginatorBase {
  127. /**
  128. * @param {?} _intl
  129. * @param {?} _changeDetectorRef
  130. */
  131. constructor(_intl, _changeDetectorRef) {
  132. super();
  133. this._intl = _intl;
  134. this._changeDetectorRef = _changeDetectorRef;
  135. this._pageIndex = 0;
  136. this._length = 0;
  137. this._pageSizeOptions = [];
  138. this._hidePageSize = false;
  139. this._showFirstLastButtons = false;
  140. /**
  141. * Event emitted when the paginator changes the page size or page index.
  142. */
  143. this.page = new EventEmitter();
  144. this._intlChanges = _intl.changes.subscribe((/**
  145. * @return {?}
  146. */
  147. () => this._changeDetectorRef.markForCheck()));
  148. }
  149. /**
  150. * The zero-based page index of the displayed list of items. Defaulted to 0.
  151. * @return {?}
  152. */
  153. get pageIndex() { return this._pageIndex; }
  154. /**
  155. * @param {?} value
  156. * @return {?}
  157. */
  158. set pageIndex(value) {
  159. this._pageIndex = Math.max(coerceNumberProperty(value), 0);
  160. this._changeDetectorRef.markForCheck();
  161. }
  162. /**
  163. * The length of the total number of items that are being paginated. Defaulted to 0.
  164. * @return {?}
  165. */
  166. get length() { return this._length; }
  167. /**
  168. * @param {?} value
  169. * @return {?}
  170. */
  171. set length(value) {
  172. this._length = coerceNumberProperty(value);
  173. this._changeDetectorRef.markForCheck();
  174. }
  175. /**
  176. * Number of items to display on a page. By default set to 50.
  177. * @return {?}
  178. */
  179. get pageSize() { return this._pageSize; }
  180. /**
  181. * @param {?} value
  182. * @return {?}
  183. */
  184. set pageSize(value) {
  185. this._pageSize = Math.max(coerceNumberProperty(value), 0);
  186. this._updateDisplayedPageSizeOptions();
  187. }
  188. /**
  189. * The set of provided page size options to display to the user.
  190. * @return {?}
  191. */
  192. get pageSizeOptions() { return this._pageSizeOptions; }
  193. /**
  194. * @param {?} value
  195. * @return {?}
  196. */
  197. set pageSizeOptions(value) {
  198. this._pageSizeOptions = (value || []).map((/**
  199. * @param {?} p
  200. * @return {?}
  201. */
  202. p => coerceNumberProperty(p)));
  203. this._updateDisplayedPageSizeOptions();
  204. }
  205. /**
  206. * Whether to hide the page size selection UI from the user.
  207. * @return {?}
  208. */
  209. get hidePageSize() { return this._hidePageSize; }
  210. /**
  211. * @param {?} value
  212. * @return {?}
  213. */
  214. set hidePageSize(value) {
  215. this._hidePageSize = coerceBooleanProperty(value);
  216. }
  217. /**
  218. * Whether to show the first/last buttons UI to the user.
  219. * @return {?}
  220. */
  221. get showFirstLastButtons() { return this._showFirstLastButtons; }
  222. /**
  223. * @param {?} value
  224. * @return {?}
  225. */
  226. set showFirstLastButtons(value) {
  227. this._showFirstLastButtons = coerceBooleanProperty(value);
  228. }
  229. /**
  230. * @return {?}
  231. */
  232. ngOnInit() {
  233. this._initialized = true;
  234. this._updateDisplayedPageSizeOptions();
  235. this._markInitialized();
  236. }
  237. /**
  238. * @return {?}
  239. */
  240. ngOnDestroy() {
  241. this._intlChanges.unsubscribe();
  242. }
  243. /**
  244. * Advances to the next page if it exists.
  245. * @return {?}
  246. */
  247. nextPage() {
  248. if (!this.hasNextPage()) {
  249. return;
  250. }
  251. /** @type {?} */
  252. const previousPageIndex = this.pageIndex;
  253. this.pageIndex++;
  254. this._emitPageEvent(previousPageIndex);
  255. }
  256. /**
  257. * Move back to the previous page if it exists.
  258. * @return {?}
  259. */
  260. previousPage() {
  261. if (!this.hasPreviousPage()) {
  262. return;
  263. }
  264. /** @type {?} */
  265. const previousPageIndex = this.pageIndex;
  266. this.pageIndex--;
  267. this._emitPageEvent(previousPageIndex);
  268. }
  269. /**
  270. * Move to the first page if not already there.
  271. * @return {?}
  272. */
  273. firstPage() {
  274. // hasPreviousPage being false implies at the start
  275. if (!this.hasPreviousPage()) {
  276. return;
  277. }
  278. /** @type {?} */
  279. const previousPageIndex = this.pageIndex;
  280. this.pageIndex = 0;
  281. this._emitPageEvent(previousPageIndex);
  282. }
  283. /**
  284. * Move to the last page if not already there.
  285. * @return {?}
  286. */
  287. lastPage() {
  288. // hasNextPage being false implies at the end
  289. if (!this.hasNextPage()) {
  290. return;
  291. }
  292. /** @type {?} */
  293. const previousPageIndex = this.pageIndex;
  294. this.pageIndex = this.getNumberOfPages() - 1;
  295. this._emitPageEvent(previousPageIndex);
  296. }
  297. /**
  298. * Whether there is a previous page.
  299. * @return {?}
  300. */
  301. hasPreviousPage() {
  302. return this.pageIndex >= 1 && this.pageSize != 0;
  303. }
  304. /**
  305. * Whether there is a next page.
  306. * @return {?}
  307. */
  308. hasNextPage() {
  309. /** @type {?} */
  310. const maxPageIndex = this.getNumberOfPages() - 1;
  311. return this.pageIndex < maxPageIndex && this.pageSize != 0;
  312. }
  313. /**
  314. * Calculate the number of pages
  315. * @return {?}
  316. */
  317. getNumberOfPages() {
  318. if (!this.pageSize) {
  319. return 0;
  320. }
  321. return Math.ceil(this.length / this.pageSize);
  322. }
  323. /**
  324. * Changes the page size so that the first item displayed on the page will still be
  325. * displayed using the new page size.
  326. *
  327. * For example, if the page size is 10 and on the second page (items indexed 10-19) then
  328. * switching so that the page size is 5 will set the third page as the current page so
  329. * that the 10th item will still be displayed.
  330. * @param {?} pageSize
  331. * @return {?}
  332. */
  333. _changePageSize(pageSize) {
  334. // Current page needs to be updated to reflect the new page size. Navigate to the page
  335. // containing the previous page's first item.
  336. /** @type {?} */
  337. const startIndex = this.pageIndex * this.pageSize;
  338. /** @type {?} */
  339. const previousPageIndex = this.pageIndex;
  340. this.pageIndex = Math.floor(startIndex / pageSize) || 0;
  341. this.pageSize = pageSize;
  342. this._emitPageEvent(previousPageIndex);
  343. }
  344. /**
  345. * Checks whether the buttons for going forwards should be disabled.
  346. * @return {?}
  347. */
  348. _nextButtonsDisabled() {
  349. return this.disabled || !this.hasNextPage();
  350. }
  351. /**
  352. * Checks whether the buttons for going backwards should be disabled.
  353. * @return {?}
  354. */
  355. _previousButtonsDisabled() {
  356. return this.disabled || !this.hasPreviousPage();
  357. }
  358. /**
  359. * Updates the list of page size options to display to the user. Includes making sure that
  360. * the page size is an option and that the list is sorted.
  361. * @private
  362. * @return {?}
  363. */
  364. _updateDisplayedPageSizeOptions() {
  365. if (!this._initialized) {
  366. return;
  367. }
  368. // If no page size is provided, use the first page size option or the default page size.
  369. if (!this.pageSize) {
  370. this._pageSize = this.pageSizeOptions.length != 0 ?
  371. this.pageSizeOptions[0] :
  372. DEFAULT_PAGE_SIZE;
  373. }
  374. this._displayedPageSizeOptions = this.pageSizeOptions.slice();
  375. if (this._displayedPageSizeOptions.indexOf(this.pageSize) === -1) {
  376. this._displayedPageSizeOptions.push(this.pageSize);
  377. }
  378. // Sort the numbers using a number-specific sort function.
  379. this._displayedPageSizeOptions.sort((/**
  380. * @param {?} a
  381. * @param {?} b
  382. * @return {?}
  383. */
  384. (a, b) => a - b));
  385. this._changeDetectorRef.markForCheck();
  386. }
  387. /**
  388. * Emits an event notifying that a change of the paginator's properties has been triggered.
  389. * @private
  390. * @param {?} previousPageIndex
  391. * @return {?}
  392. */
  393. _emitPageEvent(previousPageIndex) {
  394. this.page.emit({
  395. previousPageIndex,
  396. pageIndex: this.pageIndex,
  397. pageSize: this.pageSize,
  398. length: this.length
  399. });
  400. }
  401. }
  402. MatPaginator.decorators = [
  403. { type: Component, args: [{selector: 'mat-paginator',
  404. exportAs: 'matPaginator',
  405. template: "<div class=\"mat-paginator-outer-container\"><div class=\"mat-paginator-container\"><div class=\"mat-paginator-page-size\" *ngIf=\"!hidePageSize\"><div class=\"mat-paginator-page-size-label\">{{_intl.itemsPerPageLabel}}</div><mat-form-field *ngIf=\"_displayedPageSizeOptions.length > 1\" [color]=\"color\" class=\"mat-paginator-page-size-select\"><mat-select [value]=\"pageSize\" [disabled]=\"disabled\" [aria-label]=\"_intl.itemsPerPageLabel\" (selectionChange)=\"_changePageSize($event.value)\"><mat-option *ngFor=\"let pageSizeOption of _displayedPageSizeOptions\" [value]=\"pageSizeOption\">{{pageSizeOption}}</mat-option></mat-select></mat-form-field><div *ngIf=\"_displayedPageSizeOptions.length <= 1\">{{pageSize}}</div></div><div class=\"mat-paginator-range-actions\"><div class=\"mat-paginator-range-label\">{{_intl.getRangeLabel(pageIndex, pageSize, length)}}</div><button mat-icon-button type=\"button\" class=\"mat-paginator-navigation-first\" (click)=\"firstPage()\" [attr.aria-label]=\"_intl.firstPageLabel\" [matTooltip]=\"_intl.firstPageLabel\" [matTooltipDisabled]=\"_previousButtonsDisabled()\" [matTooltipPosition]=\"'above'\" [disabled]=\"_previousButtonsDisabled()\" *ngIf=\"showFirstLastButtons\"><svg class=\"mat-paginator-icon\" viewBox=\"0 0 24 24\" focusable=\"false\"><path d=\"M18.41 16.59L13.82 12l4.59-4.59L17 6l-6 6 6 6zM6 6h2v12H6z\"/></svg></button> <button mat-icon-button type=\"button\" class=\"mat-paginator-navigation-previous\" (click)=\"previousPage()\" [attr.aria-label]=\"_intl.previousPageLabel\" [matTooltip]=\"_intl.previousPageLabel\" [matTooltipDisabled]=\"_previousButtonsDisabled()\" [matTooltipPosition]=\"'above'\" [disabled]=\"_previousButtonsDisabled()\"><svg class=\"mat-paginator-icon\" viewBox=\"0 0 24 24\" focusable=\"false\"><path d=\"M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z\"/></svg></button> <button mat-icon-button type=\"button\" class=\"mat-paginator-navigation-next\" (click)=\"nextPage()\" [attr.aria-label]=\"_intl.nextPageLabel\" [matTooltip]=\"_intl.nextPageLabel\" [matTooltipDisabled]=\"_nextButtonsDisabled()\" [matTooltipPosition]=\"'above'\" [disabled]=\"_nextButtonsDisabled()\"><svg class=\"mat-paginator-icon\" viewBox=\"0 0 24 24\" focusable=\"false\"><path d=\"M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z\"/></svg></button> <button mat-icon-button type=\"button\" class=\"mat-paginator-navigation-last\" (click)=\"lastPage()\" [attr.aria-label]=\"_intl.lastPageLabel\" [matTooltip]=\"_intl.lastPageLabel\" [matTooltipDisabled]=\"_nextButtonsDisabled()\" [matTooltipPosition]=\"'above'\" [disabled]=\"_nextButtonsDisabled()\" *ngIf=\"showFirstLastButtons\"><svg class=\"mat-paginator-icon\" viewBox=\"0 0 24 24\" focusable=\"false\"><path d=\"M5.59 7.41L10.18 12l-4.59 4.59L7 18l6-6-6-6zM16 6h2v12h-2z\"/></svg></button></div></div></div>",
  406. styles: [".mat-paginator{display:block}.mat-paginator-outer-container{display:flex}.mat-paginator-container{display:flex;align-items:center;justify-content:flex-end;min-height:56px;padding:0 8px;flex-wrap:wrap-reverse;width:100%}.mat-paginator-page-size{display:flex;align-items:baseline;margin-right:8px}[dir=rtl] .mat-paginator-page-size{margin-right:0;margin-left:8px}.mat-paginator-page-size-label{margin:0 4px}.mat-paginator-page-size-select{margin:6px 4px 0 4px;width:56px}.mat-paginator-page-size-select.mat-form-field-appearance-outline{width:64px}.mat-paginator-page-size-select.mat-form-field-appearance-fill{width:64px}.mat-paginator-range-label{margin:0 32px 0 24px}.mat-paginator-range-actions{display:flex;align-items:center}.mat-paginator-icon{width:28px;fill:currentColor}[dir=rtl] .mat-paginator-icon{transform:rotate(180deg)}"],
  407. inputs: ['disabled'],
  408. host: {
  409. 'class': 'mat-paginator',
  410. },
  411. changeDetection: ChangeDetectionStrategy.OnPush,
  412. encapsulation: ViewEncapsulation.None,
  413. },] },
  414. ];
  415. /** @nocollapse */
  416. MatPaginator.ctorParameters = () => [
  417. { type: MatPaginatorIntl },
  418. { type: ChangeDetectorRef }
  419. ];
  420. MatPaginator.propDecorators = {
  421. color: [{ type: Input }],
  422. pageIndex: [{ type: Input }],
  423. length: [{ type: Input }],
  424. pageSize: [{ type: Input }],
  425. pageSizeOptions: [{ type: Input }],
  426. hidePageSize: [{ type: Input }],
  427. showFirstLastButtons: [{ type: Input }],
  428. page: [{ type: Output }]
  429. };
  430. /**
  431. * @fileoverview added by tsickle
  432. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  433. */
  434. class MatPaginatorModule {
  435. }
  436. MatPaginatorModule.decorators = [
  437. { type: NgModule, args: [{
  438. imports: [
  439. CommonModule,
  440. MatButtonModule,
  441. MatSelectModule,
  442. MatTooltipModule,
  443. ],
  444. exports: [MatPaginator],
  445. declarations: [MatPaginator],
  446. providers: [MAT_PAGINATOR_INTL_PROVIDER],
  447. },] },
  448. ];
  449. /**
  450. * @fileoverview added by tsickle
  451. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  452. */
  453. /**
  454. * @fileoverview added by tsickle
  455. * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  456. */
  457. export { MatPaginatorModule, PageEvent, MatPaginator, MAT_PAGINATOR_INTL_PROVIDER_FACTORY, MatPaginatorIntl, MAT_PAGINATOR_INTL_PROVIDER };
  458. //# sourceMappingURL=paginator.js.map