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.
This commit is contained in:
Kristiyan Kostadinov
2018-10-23 20:02:50 +02:00
committed by mmalerba
parent 83fc823715
commit cb4f5a07d5
5 changed files with 58 additions and 14 deletions
@@ -20,12 +20,14 @@
<mat-slide-toggle [(ngModel)]="hidePageSize">Hide page size</mat-slide-toggle>
<mat-slide-toggle [(ngModel)]="showPageSizeOptions">Show multiple page size options</mat-slide-toggle>
<mat-slide-toggle [(ngModel)]="showFirstLastButtons">Show first/last buttons</mat-slide-toggle>
<mat-slide-toggle [(ngModel)]="disabled">Disabled</mat-slide-toggle>
</div>
<mat-paginator #paginator
(page)="handlePageEvent($event)"
[length]="length"
[pageSize]="pageSize"
[disabled]="disabled"
[showFirstLastButtons]="showFirstLastButtons"
[pageSizeOptions]="showPageSizeOptions ? pageSizeOptions : []"
[hidePageSize]="hidePageSize"
+1
View File
@@ -25,6 +25,7 @@ export class PaginatorDemo {
hidePageSize = false;
showPageSizeOptions = true;
showFirstLastButtons = true;
disabled = false;
pageEvent: PageEvent;
+9 -8
View File
@@ -11,6 +11,7 @@
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">
@@ -32,9 +33,9 @@
(click)="firstPage()"
[attr.aria-label]="_intl.firstPageLabel"
[matTooltip]="_intl.firstPageLabel"
[matTooltipDisabled]="!hasPreviousPage()"
[matTooltipDisabled]="_previousButtonsDisabled()"
[matTooltipPosition]="'above'"
[disabled]="!hasPreviousPage()"
[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"/>
@@ -45,9 +46,9 @@
(click)="previousPage()"
[attr.aria-label]="_intl.previousPageLabel"
[matTooltip]="_intl.previousPageLabel"
[matTooltipDisabled]="!hasPreviousPage()"
[matTooltipDisabled]="_previousButtonsDisabled()"
[matTooltipPosition]="'above'"
[disabled]="!hasPreviousPage()">
[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>
@@ -57,9 +58,9 @@
(click)="nextPage()"
[attr.aria-label]="_intl.nextPageLabel"
[matTooltip]="_intl.nextPageLabel"
[matTooltipDisabled]="!hasNextPage()"
[matTooltipDisabled]="_nextButtonsDisabled()"
[matTooltipPosition]="'above'"
[disabled]="!hasNextPage()">
[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>
@@ -69,9 +70,9 @@
(click)="lastPage()"
[attr.aria-label]="_intl.lastPageLabel"
[matTooltip]="_intl.lastPageLabel"
[matTooltipDisabled]="!hasNextPage()"
[matTooltipDisabled]="_nextButtonsDisabled()"
[matTooltipPosition]="'above'"
[disabled]="!hasNextPage()"
[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"/>
+28 -3
View File
@@ -1,11 +1,11 @@
import {async, ComponentFixture, TestBed, inject, tick, fakeAsync} from '@angular/core/testing';
import {MatPaginatorModule} from './index';
import {MatPaginator} from './paginator';
import {Component, ViewChild} from '@angular/core';
import {MatPaginatorIntl} from './paginator-intl';
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
import {dispatchMouseEvent} from '@angular/cdk/testing';
import {ThemePalette} from '@angular/material/core';
import {MatSelect} from '@angular/material/select';
import {By} from '@angular/platform-browser';
import {MatPaginatorModule, MatPaginator, MatPaginatorIntl} from './index';
describe('MatPaginator', () => {
@@ -391,6 +391,29 @@ describe('MatPaginator', () => {
.toBeNull('Expected select to be removed.');
});
it('should be able to disable all the controls in the paginator via the binding', () => {
const select: MatSelect = fixture.debugElement.query(By.directive(MatSelect)).componentInstance;
fixture.componentInstance.pageIndex = 1;
fixture.componentInstance.showFirstLastButtons = true;
fixture.detectChanges();
expect(select.disabled).toBe(false);
expect(getPreviousButton(fixture).hasAttribute('disabled')).toBe(false);
expect(getNextButton(fixture).hasAttribute('disabled')).toBe(false);
expect(getFirstButton(fixture).hasAttribute('disabled')).toBe(false);
expect(getLastButton(fixture).hasAttribute('disabled')).toBe(false);
fixture.componentInstance.disabled = true;
fixture.detectChanges();
expect(select.disabled).toBe(true);
expect(getPreviousButton(fixture).hasAttribute('disabled')).toBe(true);
expect(getNextButton(fixture).hasAttribute('disabled')).toBe(true);
expect(getFirstButton(fixture).hasAttribute('disabled')).toBe(true);
expect(getLastButton(fixture).hasAttribute('disabled')).toBe(true);
});
});
function getPreviousButton(fixture: ComponentFixture<any>) {
@@ -418,6 +441,7 @@ function getLastButton(fixture: ComponentFixture<any>) {
[showFirstLastButtons]="showFirstLastButtons"
[length]="length"
[color]="color"
[disabled]="disabled"
(page)="pageEvent($event)">
</mat-paginator>
`,
@@ -429,6 +453,7 @@ class MatPaginatorApp {
hidePageSize = false;
showFirstLastButtons = false;
length = 100;
disabled: boolean;
pageEvent = jasmine.createSpy('page event');
color: ThemePalette;
+18 -3
View File
@@ -25,6 +25,9 @@ import {
HasInitializedCtor,
mixinInitialized,
ThemePalette,
mixinDisabled,
CanDisableCtor,
CanDisable,
} from '@angular/material/core';
/** 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 {
// Boilerplate for applying mixins to MatPaginator.
/** @docs-private */
export class MatPaginatorBase {}
export const _MatPaginatorBase: HasInitializedCtor & typeof MatPaginatorBase =
mixinInitialized(MatPaginatorBase);
export const _MatPaginatorBase: CanDisableCtor & HasInitializedCtor & typeof MatPaginatorBase =
mixinDisabled(mixinInitialized(MatPaginatorBase));
/**
* Component to provide navigation between paged information. Displays the size of the current
@@ -68,13 +71,15 @@ export const _MatPaginatorBase: HasInitializedCtor & typeof MatPaginatorBase =
exportAs: 'matPaginator',
templateUrl: 'paginator.html',
styleUrls: ['paginator.css'],
inputs: ['disabled'],
host: {
'class': 'mat-paginator',
},
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
})
export class MatPaginator extends _MatPaginatorBase implements OnInit, OnDestroy, HasInitialized {
export class MatPaginator extends _MatPaginatorBase implements OnInit, OnDestroy, CanDisable,
HasInitialized {
private _initialized: boolean;
private _intlChanges: Subscription;
@@ -234,6 +239,16 @@ export class MatPaginator extends _MatPaginatorBase implements OnInit, OnDestroy
this._emitPageEvent(previousPageIndex);
}
/** Checks whether the buttons for going forwards should be disabled. */
_nextButtonsDisabled() {
return this.disabled || !this.hasNextPage();
}
/** Checks whether the buttons for going backwards should be disabled. */
_previousButtonsDisabled() {
return this.disabled || !this.hasPreviousPage();
}
/**
* Updates the list of page size options to display to the user. Includes making sure that
* the page size is an option and that the list is sorted.