Skip to content

Commit cb4f5a0

Browse files
crisbetommalerba
authored andcommitted
feat(paginator): allow paginator to be disabled (#13146)
Adds the ability for the paginator to be disabled. This is useful for cases like long-running HTTP requests where the user shouldn't be able to change the current page while the data is still loading. Fixes #13145.
1 parent 83fc823 commit cb4f5a0

File tree

5 files changed

+58
-14
lines changed

5 files changed

+58
-14
lines changed

src/demo-app/paginator/paginator-demo.html

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,12 +20,14 @@ <h2>No inputs</h2>
2020
<mat-slide-toggle [(ngModel)]="hidePageSize">Hide page size</mat-slide-toggle>
2121
<mat-slide-toggle [(ngModel)]="showPageSizeOptions">Show multiple page size options</mat-slide-toggle>
2222
<mat-slide-toggle [(ngModel)]="showFirstLastButtons">Show first/last buttons</mat-slide-toggle>
23+
<mat-slide-toggle [(ngModel)]="disabled">Disabled</mat-slide-toggle>
2324
</div>
2425

2526
<mat-paginator #paginator
2627
(page)="handlePageEvent($event)"
2728
[length]="length"
2829
[pageSize]="pageSize"
30+
[disabled]="disabled"
2931
[showFirstLastButtons]="showFirstLastButtons"
3032
[pageSizeOptions]="showPageSizeOptions ? pageSizeOptions : []"
3133
[hidePageSize]="hidePageSize"

src/demo-app/paginator/paginator-demo.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ export class PaginatorDemo {
2525
hidePageSize = false;
2626
showPageSizeOptions = true;
2727
showFirstLastButtons = true;
28+
disabled = false;
2829

2930
pageEvent: PageEvent;
3031

src/lib/paginator/paginator.html

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
class="mat-paginator-page-size-select">
1212
<mat-select
1313
[value]="pageSize"
14+
[disabled]="disabled"
1415
[aria-label]="_intl.itemsPerPageLabel"
1516
(selectionChange)="_changePageSize($event.value)">
1617
<mat-option *ngFor="let pageSizeOption of _displayedPageSizeOptions" [value]="pageSizeOption">
@@ -32,9 +33,9 @@
3233
(click)="firstPage()"
3334
[attr.aria-label]="_intl.firstPageLabel"
3435
[matTooltip]="_intl.firstPageLabel"
35-
[matTooltipDisabled]="!hasPreviousPage()"
36+
[matTooltipDisabled]="_previousButtonsDisabled()"
3637
[matTooltipPosition]="'above'"
37-
[disabled]="!hasPreviousPage()"
38+
[disabled]="_previousButtonsDisabled()"
3839
*ngIf="showFirstLastButtons">
3940
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
4041
<path d="M18.41 16.59L13.82 12l4.59-4.59L17 6l-6 6 6 6zM6 6h2v12H6z"/>
@@ -45,9 +46,9 @@
4546
(click)="previousPage()"
4647
[attr.aria-label]="_intl.previousPageLabel"
4748
[matTooltip]="_intl.previousPageLabel"
48-
[matTooltipDisabled]="!hasPreviousPage()"
49+
[matTooltipDisabled]="_previousButtonsDisabled()"
4950
[matTooltipPosition]="'above'"
50-
[disabled]="!hasPreviousPage()">
51+
[disabled]="_previousButtonsDisabled()">
5152
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
5253
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
5354
</svg>
@@ -57,9 +58,9 @@
5758
(click)="nextPage()"
5859
[attr.aria-label]="_intl.nextPageLabel"
5960
[matTooltip]="_intl.nextPageLabel"
60-
[matTooltipDisabled]="!hasNextPage()"
61+
[matTooltipDisabled]="_nextButtonsDisabled()"
6162
[matTooltipPosition]="'above'"
62-
[disabled]="!hasNextPage()">
63+
[disabled]="_nextButtonsDisabled()">
6364
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
6465
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>
6566
</svg>
@@ -69,9 +70,9 @@
6970
(click)="lastPage()"
7071
[attr.aria-label]="_intl.lastPageLabel"
7172
[matTooltip]="_intl.lastPageLabel"
72-
[matTooltipDisabled]="!hasNextPage()"
73+
[matTooltipDisabled]="_nextButtonsDisabled()"
7374
[matTooltipPosition]="'above'"
74-
[disabled]="!hasNextPage()"
75+
[disabled]="_nextButtonsDisabled()"
7576
*ngIf="showFirstLastButtons">
7677
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
7778
<path d="M5.59 7.41L10.18 12l-4.59 4.59L7 18l6-6-6-6zM16 6h2v12h-2z"/>

src/lib/paginator/paginator.spec.ts

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import {async, ComponentFixture, TestBed, inject, tick, fakeAsync} from '@angular/core/testing';
2-
import {MatPaginatorModule} from './index';
3-
import {MatPaginator} from './paginator';
42
import {Component, ViewChild} from '@angular/core';
5-
import {MatPaginatorIntl} from './paginator-intl';
63
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
74
import {dispatchMouseEvent} from '@angular/cdk/testing';
85
import {ThemePalette} from '@angular/material/core';
6+
import {MatSelect} from '@angular/material/select';
7+
import {By} from '@angular/platform-browser';
8+
import {MatPaginatorModule, MatPaginator, MatPaginatorIntl} from './index';
99

1010

1111
describe('MatPaginator', () => {
@@ -391,6 +391,29 @@ describe('MatPaginator', () => {
391391
.toBeNull('Expected select to be removed.');
392392
});
393393

394+
it('should be able to disable all the controls in the paginator via the binding', () => {
395+
const select: MatSelect = fixture.debugElement.query(By.directive(MatSelect)).componentInstance;
396+
397+
fixture.componentInstance.pageIndex = 1;
398+
fixture.componentInstance.showFirstLastButtons = true;
399+
fixture.detectChanges();
400+
401+
expect(select.disabled).toBe(false);
402+
expect(getPreviousButton(fixture).hasAttribute('disabled')).toBe(false);
403+
expect(getNextButton(fixture).hasAttribute('disabled')).toBe(false);
404+
expect(getFirstButton(fixture).hasAttribute('disabled')).toBe(false);
405+
expect(getLastButton(fixture).hasAttribute('disabled')).toBe(false);
406+
407+
fixture.componentInstance.disabled = true;
408+
fixture.detectChanges();
409+
410+
expect(select.disabled).toBe(true);
411+
expect(getPreviousButton(fixture).hasAttribute('disabled')).toBe(true);
412+
expect(getNextButton(fixture).hasAttribute('disabled')).toBe(true);
413+
expect(getFirstButton(fixture).hasAttribute('disabled')).toBe(true);
414+
expect(getLastButton(fixture).hasAttribute('disabled')).toBe(true);
415+
});
416+
394417
});
395418

396419
function getPreviousButton(fixture: ComponentFixture<any>) {
@@ -418,6 +441,7 @@ function getLastButton(fixture: ComponentFixture<any>) {
418441
[showFirstLastButtons]="showFirstLastButtons"
419442
[length]="length"
420443
[color]="color"
444+
[disabled]="disabled"
421445
(page)="pageEvent($event)">
422446
</mat-paginator>
423447
`,
@@ -429,6 +453,7 @@ class MatPaginatorApp {
429453
hidePageSize = false;
430454
showFirstLastButtons = false;
431455
length = 100;
456+
disabled: boolean;
432457
pageEvent = jasmine.createSpy('page event');
433458
color: ThemePalette;
434459

src/lib/paginator/paginator.ts

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,9 @@ import {
2525
HasInitializedCtor,
2626
mixinInitialized,
2727
ThemePalette,
28+
mixinDisabled,
29+
CanDisableCtor,
30+
CanDisable,
2831
} from '@angular/material/core';
2932

3033
/** The default page size if there is no page size and there are no provided page size options. */
@@ -54,8 +57,8 @@ export class PageEvent {
5457
// Boilerplate for applying mixins to MatPaginator.
5558
/** @docs-private */
5659
export class MatPaginatorBase {}
57-
export const _MatPaginatorBase: HasInitializedCtor & typeof MatPaginatorBase =
58-
mixinInitialized(MatPaginatorBase);
60+
export const _MatPaginatorBase: CanDisableCtor & HasInitializedCtor & typeof MatPaginatorBase =
61+
mixinDisabled(mixinInitialized(MatPaginatorBase));
5962

6063
/**
6164
* Component to provide navigation between paged information. Displays the size of the current
@@ -68,13 +71,15 @@ export const _MatPaginatorBase: HasInitializedCtor & typeof MatPaginatorBase =
6871
exportAs: 'matPaginator',
6972
templateUrl: 'paginator.html',
7073
styleUrls: ['paginator.css'],
74+
inputs: ['disabled'],
7175
host: {
7276
'class': 'mat-paginator',
7377
},
7478
changeDetection: ChangeDetectionStrategy.OnPush,
7579
encapsulation: ViewEncapsulation.None,
7680
})
77-
export class MatPaginator extends _MatPaginatorBase implements OnInit, OnDestroy, HasInitialized {
81+
export class MatPaginator extends _MatPaginatorBase implements OnInit, OnDestroy, CanDisable,
82+
HasInitialized {
7883
private _initialized: boolean;
7984
private _intlChanges: Subscription;
8085

@@ -234,6 +239,16 @@ export class MatPaginator extends _MatPaginatorBase implements OnInit, OnDestroy
234239
this._emitPageEvent(previousPageIndex);
235240
}
236241

242+
/** Checks whether the buttons for going forwards should be disabled. */
243+
_nextButtonsDisabled() {
244+
return this.disabled || !this.hasNextPage();
245+
}
246+
247+
/** Checks whether the buttons for going backwards should be disabled. */
248+
_previousButtonsDisabled() {
249+
return this.disabled || !this.hasPreviousPage();
250+
}
251+
237252
/**
238253
* Updates the list of page size options to display to the user. Includes making sure that
239254
* the page size is an option and that the list is sorted.

0 commit comments

Comments
 (0)