Skip to content

Commit e8d59e5

Browse files
committed
feat(paginator): allow paginator to be disabled
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 9ab2c90 commit e8d59e5

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,11 +20,13 @@ <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 (page)="handlePageEvent($event)"
2627
[length]="length"
2728
[pageSize]="pageSize"
29+
[disabled]="disabled"
2830
[showFirstLastButtons]="showFirstLastButtons"
2931
[pageSizeOptions]="showPageSizeOptions ? pageSizeOptions : []"
3032
[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
<mat-select
1212
[value]="pageSize"
1313
[aria-label]="_intl.itemsPerPageLabel"
14+
[disabled]="disabled"
1415
(selectionChange)="_changePageSize($event.value)">
1516
<mat-option *ngFor="let pageSizeOption of _displayedPageSizeOptions" [value]="pageSizeOption">
1617
{{pageSizeOption}}
@@ -31,9 +32,9 @@
3132
(click)="firstPage()"
3233
[attr.aria-label]="_intl.firstPageLabel"
3334
[matTooltip]="_intl.firstPageLabel"
34-
[matTooltipDisabled]="!hasPreviousPage()"
35+
[matTooltipDisabled]="_previousButtonsDisabled()"
3536
[matTooltipPosition]="'above'"
36-
[disabled]="!hasPreviousPage()"
37+
[disabled]="_previousButtonsDisabled()"
3738
*ngIf="showFirstLastButtons">
3839
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
3940
<path d="M18.41 16.59L13.82 12l4.59-4.59L17 6l-6 6 6 6zM6 6h2v12H6z"/>
@@ -44,9 +45,9 @@
4445
(click)="previousPage()"
4546
[attr.aria-label]="_intl.previousPageLabel"
4647
[matTooltip]="_intl.previousPageLabel"
47-
[matTooltipDisabled]="!hasPreviousPage()"
48+
[matTooltipDisabled]="_previousButtonsDisabled()"
4849
[matTooltipPosition]="'above'"
49-
[disabled]="!hasPreviousPage()">
50+
[disabled]="_previousButtonsDisabled()">
5051
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
5152
<path d="M15.41 7.41L14 6l-6 6 6 6 1.41-1.41L10.83 12z"/>
5253
</svg>
@@ -56,9 +57,9 @@
5657
(click)="nextPage()"
5758
[attr.aria-label]="_intl.nextPageLabel"
5859
[matTooltip]="_intl.nextPageLabel"
59-
[matTooltipDisabled]="!hasNextPage()"
60+
[matTooltipDisabled]="_nextButtonsDisabled()"
6061
[matTooltipPosition]="'above'"
61-
[disabled]="!hasNextPage()">
62+
[disabled]="_nextButtonsDisabled()">
6263
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
6364
<path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"/>
6465
</svg>
@@ -68,9 +69,9 @@
6869
(click)="lastPage()"
6970
[attr.aria-label]="_intl.lastPageLabel"
7071
[matTooltip]="_intl.lastPageLabel"
71-
[matTooltipDisabled]="!hasNextPage()"
72+
[matTooltipDisabled]="_nextButtonsDisabled()"
7273
[matTooltipPosition]="'above'"
73-
[disabled]="!hasNextPage()"
74+
[disabled]="_nextButtonsDisabled()"
7475
*ngIf="showFirstLastButtons">
7576
<svg class="mat-paginator-icon" viewBox="0 0 24 24" focusable="false">
7677
<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', () => {
@@ -374,6 +374,29 @@ describe('MatPaginator', () => {
374374
.toBeNull('Expected select to be removed.');
375375
});
376376

377+
it('should be able to disable all the controls in the paginator via the binding', () => {
378+
const select: MatSelect = fixture.debugElement.query(By.directive(MatSelect)).componentInstance;
379+
380+
fixture.componentInstance.pageIndex = 1;
381+
fixture.componentInstance.showFirstLastButtons = true;
382+
fixture.detectChanges();
383+
384+
expect(select.disabled).toBe(false);
385+
expect(getPreviousButton(fixture).hasAttribute('disabled')).toBe(false);
386+
expect(getNextButton(fixture).hasAttribute('disabled')).toBe(false);
387+
expect(getFirstButton(fixture).hasAttribute('disabled')).toBe(false);
388+
expect(getLastButton(fixture).hasAttribute('disabled')).toBe(false);
389+
390+
fixture.componentInstance.disabled = true;
391+
fixture.detectChanges();
392+
393+
expect(select.disabled).toBe(true);
394+
expect(getPreviousButton(fixture).hasAttribute('disabled')).toBe(true);
395+
expect(getNextButton(fixture).hasAttribute('disabled')).toBe(true);
396+
expect(getFirstButton(fixture).hasAttribute('disabled')).toBe(true);
397+
expect(getLastButton(fixture).hasAttribute('disabled')).toBe(true);
398+
});
399+
377400
});
378401

379402
function getPreviousButton(fixture: ComponentFixture<any>) {
@@ -401,6 +424,7 @@ function getLastButton(fixture: ComponentFixture<any>) {
401424
[showFirstLastButtons]="showFirstLastButtons"
402425
[length]="length"
403426
[color]="color"
427+
[disabled]="disabled"
404428
(page)="pageEvent($event)">
405429
</mat-paginator>
406430
`,
@@ -412,6 +436,7 @@ class MatPaginatorApp {
412436
hidePageSize = false;
413437
showFirstLastButtons = false;
414438
length = 100;
439+
disabled: boolean;
415440
pageEvent = jasmine.createSpy('page event');
416441
color: ThemePalette;
417442

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

@@ -230,6 +235,16 @@ export class MatPaginator extends _MatPaginatorBase implements OnInit, OnDestroy
230235
this._emitPageEvent(previousPageIndex);
231236
}
232237

238+
/** Checks whether the buttons for going forwards should be disabled. */
239+
_nextButtonsDisabled() {
240+
return this.disabled || !this.hasNextPage();
241+
}
242+
243+
/** Checks whether the buttons for going backwards should be disabled. */
244+
_previousButtonsDisabled() {
245+
return this.disabled || !this.hasPreviousPage();
246+
}
247+
233248
/**
234249
* Updates the list of page size options to display to the user. Includes making sure that
235250
* the page size is an option and that the list is sorted.

0 commit comments

Comments
 (0)