mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
feat(pagination): initial pagination component (#5156)
This commit is contained in:
committed by
Jeremy Elbourn
parent
7b2d4ae601
commit
85fb00a151
Generated
+4
-4
@@ -4169,7 +4169,7 @@
|
|||||||
"glob": {
|
"glob": {
|
||||||
"version": "7.1.2",
|
"version": "7.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
|
||||||
"integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==",
|
"integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"glob-base": {
|
"glob-base": {
|
||||||
@@ -8070,7 +8070,7 @@
|
|||||||
"npmlog": {
|
"npmlog": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.0.tgz",
|
||||||
"integrity": "sha512-ocolIkZYZt8UveuiDS0yAkkIjid1o7lPG8cYm05yNYzBn8ykQtaiPMEGp8fY9tKdDgm8okpdKzkvu1y9hUYugA==",
|
"integrity": "sha1-3Fm+6F9k8A7UJO+yrweD3yXRwLU=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"null-check": {
|
"null-check": {
|
||||||
@@ -11254,7 +11254,7 @@
|
|||||||
"wide-align": {
|
"wide-align": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.2.tgz",
|
||||||
"integrity": "sha512-ijDLlyQ7s6x1JgCLur53osjm/UXUYD9+0PbYKrBsYisYXzCxN+HC3mYDNy/dWdmf3AwqwU3CXwDCvsNgGK1S0w==",
|
"integrity": "sha1-Vx4PGwYEY268DfwhsDObvjE0FxA=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"widest-line": {
|
"widest-line": {
|
||||||
@@ -11316,7 +11316,7 @@
|
|||||||
"write-file-atomic": {
|
"write-file-atomic": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.1.0.tgz",
|
||||||
"integrity": "sha512-0TZ20a+xcIl4u0+Mj5xDH2yOWdmQiXlKf9Hm+TgDXjTMsEYb+gDrmb8e8UNAzMCitX8NBqG4Z/FUQIyzv/R1JQ==",
|
"integrity": "sha1-F2n0tVHu3OQZ8FBd6uLiZ2NULTc=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"write-file-stdout": {
|
"write-file-stdout": {
|
||||||
|
|||||||
@@ -78,4 +78,11 @@
|
|||||||
}">
|
}">
|
||||||
</cdk-row>
|
</cdk-row>
|
||||||
</cdk-table>
|
</cdk-table>
|
||||||
|
|
||||||
|
<md-paginator #paginator
|
||||||
|
[length]="_peopleDatabase.data.length"
|
||||||
|
[pageIndex]="0"
|
||||||
|
[pageSize]="10"
|
||||||
|
[pageSizeOptions]="[5, 10, 25, 100]">
|
||||||
|
</md-paginator>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import {Component} from '@angular/core';
|
import {Component, ViewChild} from '@angular/core';
|
||||||
import {PeopleDatabase, UserData} from './people-database';
|
import {PeopleDatabase, UserData} from './people-database';
|
||||||
import {PersonDataSource} from './person-data-source';
|
import {PersonDataSource} from './person-data-source';
|
||||||
|
import {MdPaginator} from '@angular/material';
|
||||||
|
|
||||||
export type UserProperties = 'userId' | 'userName' | 'progress' | 'color' | undefined;
|
export type UserProperties = 'userId' | 'userName' | 'progress' | 'color' | undefined;
|
||||||
|
|
||||||
@@ -19,13 +20,17 @@ export class DataTableDemo {
|
|||||||
changeReferences = false;
|
changeReferences = false;
|
||||||
highlights = new Set<string>();
|
highlights = new Set<string>();
|
||||||
|
|
||||||
constructor(public _peopleDatabase: PeopleDatabase) {
|
@ViewChild(MdPaginator) _paginator: MdPaginator;
|
||||||
|
|
||||||
|
constructor(public _peopleDatabase: PeopleDatabase) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
this.connect();
|
this.connect();
|
||||||
}
|
}
|
||||||
|
|
||||||
connect() {
|
connect() {
|
||||||
this.propertiesToDisplay = ['userId', 'userName', 'progress', 'color'];
|
this.propertiesToDisplay = ['userId', 'userName', 'progress', 'color'];
|
||||||
this.dataSource = new PersonDataSource(this._peopleDatabase);
|
this.dataSource = new PersonDataSource(this._peopleDatabase, this._paginator);
|
||||||
this._peopleDatabase.initialize();
|
this._peopleDatabase.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,34 +1,58 @@
|
|||||||
import {CollectionViewer, DataSource} from '@angular/material';
|
import {CollectionViewer, DataSource, MdPaginator} from '@angular/material';
|
||||||
import {Observable} from 'rxjs/Observable';
|
import {Observable} from 'rxjs/Observable';
|
||||||
import {PeopleDatabase, UserData} from './people-database';
|
import {PeopleDatabase, UserData} from './people-database';
|
||||||
|
import {BehaviorSubject} from 'rxjs/BehaviorSubject';
|
||||||
|
|
||||||
export class PersonDataSource extends DataSource<any> {
|
export class PersonDataSource extends DataSource<any> {
|
||||||
|
/** Data that should be displayed by the table. */
|
||||||
|
_displayData = new BehaviorSubject<UserData[]>([]);
|
||||||
|
|
||||||
|
/** Cached data provided by the display data. */
|
||||||
_renderedData: any[] = [];
|
_renderedData: any[] = [];
|
||||||
|
|
||||||
constructor(private _peopleDatabase: PeopleDatabase) {
|
constructor(private _peopleDatabase: PeopleDatabase,
|
||||||
|
private _paginator: MdPaginator) {
|
||||||
super();
|
super();
|
||||||
|
|
||||||
|
// Subscribe to page changes and database changes by clearing the cached data and
|
||||||
|
// determining the updated display data.
|
||||||
|
Observable.merge(this._paginator.page, this._peopleDatabase.dataChange).subscribe(() => {
|
||||||
|
this._renderedData = [];
|
||||||
|
this.updateDisplayData();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
connect(collectionViewer: CollectionViewer): Observable<UserData[]> {
|
connect(collectionViewer: CollectionViewer): Observable<UserData[]> {
|
||||||
const changeStreams = Observable.combineLatest(
|
this.updateDisplayData();
|
||||||
collectionViewer.viewChange,
|
|
||||||
this._peopleDatabase.dataChange);
|
|
||||||
return changeStreams.map((result: any[]) => {
|
|
||||||
const view: {start: number, end: number} = result[0];
|
|
||||||
|
|
||||||
// Set the rendered rows length to the virtual page size. Fill in the data provided
|
const streams = [collectionViewer.viewChange, this._displayData];
|
||||||
// from the index start until the end index or pagination size, whichever is smaller.
|
return Observable.combineLatest(streams)
|
||||||
this._renderedData.length = this._peopleDatabase.data.length;
|
.map((results: [{start: number, end: number}, UserData[]]) => {
|
||||||
|
const [view, data] = results;
|
||||||
|
|
||||||
const buffer = 20;
|
// Set the rendered rows length to the virtual page size. Fill in the data provided
|
||||||
let rangeStart = Math.max(0, view.start - buffer);
|
// from the index start until the end index or pagination size, whichever is smaller.
|
||||||
let rangeEnd = Math.min(this._peopleDatabase.data.length, view.end + buffer);
|
this._renderedData.length = data.length;
|
||||||
|
|
||||||
for (let i = rangeStart; i < rangeEnd; i++) {
|
const buffer = 20;
|
||||||
this._renderedData[i] = this._peopleDatabase.data[i];
|
let rangeStart = Math.max(0, view.start - buffer);
|
||||||
}
|
let rangeEnd = Math.min(data.length, view.end + buffer);
|
||||||
|
|
||||||
return this._renderedData;
|
for (let i = rangeStart; i < rangeEnd; i++) {
|
||||||
});
|
this._renderedData[i] = data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this._renderedData;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
updateDisplayData() {
|
||||||
|
const data = this._peopleDatabase.data.slice();
|
||||||
|
|
||||||
|
// Grab the page's slice of data.
|
||||||
|
const startIndex = this._paginator.pageIndex * this._paginator.pageSize;
|
||||||
|
const paginatedData = data.splice(startIndex, this._paginator.pageSize);
|
||||||
|
|
||||||
|
this._displayData.next(paginatedData);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,6 +61,7 @@ import {
|
|||||||
MdListModule,
|
MdListModule,
|
||||||
MdMenuModule,
|
MdMenuModule,
|
||||||
MdNativeDateModule,
|
MdNativeDateModule,
|
||||||
|
MdPaginatorModule,
|
||||||
MdProgressBarModule,
|
MdProgressBarModule,
|
||||||
MdProgressSpinnerModule,
|
MdProgressSpinnerModule,
|
||||||
MdRadioModule,
|
MdRadioModule,
|
||||||
@@ -98,6 +99,7 @@ import {TableHeaderDemo} from './data-table/table-header-demo';
|
|||||||
MdListModule,
|
MdListModule,
|
||||||
MdMenuModule,
|
MdMenuModule,
|
||||||
MdCoreModule,
|
MdCoreModule,
|
||||||
|
MdPaginatorModule,
|
||||||
MdProgressBarModule,
|
MdProgressBarModule,
|
||||||
MdProgressSpinnerModule,
|
MdProgressSpinnerModule,
|
||||||
MdRadioModule,
|
MdRadioModule,
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
@import '../../input/input-theme';
|
@import '../../input/input-theme';
|
||||||
@import '../../list/list-theme';
|
@import '../../list/list-theme';
|
||||||
@import '../../menu/menu-theme';
|
@import '../../menu/menu-theme';
|
||||||
|
@import '../../paginator/paginator-theme';
|
||||||
@import '../../progress-bar/progress-bar-theme';
|
@import '../../progress-bar/progress-bar-theme';
|
||||||
@import '../../progress-spinner/progress-spinner-theme';
|
@import '../../progress-spinner/progress-spinner-theme';
|
||||||
@import '../../radio/radio-theme';
|
@import '../../radio/radio-theme';
|
||||||
@@ -44,6 +45,7 @@
|
|||||||
@include mat-input-theme($theme);
|
@include mat-input-theme($theme);
|
||||||
@include mat-list-theme($theme);
|
@include mat-list-theme($theme);
|
||||||
@include mat-menu-theme($theme);
|
@include mat-menu-theme($theme);
|
||||||
|
@include mat-paginator-theme($theme);
|
||||||
@include mat-progress-bar-theme($theme);
|
@include mat-progress-bar-theme($theme);
|
||||||
@include mat-progress-spinner-theme($theme);
|
@include mat-progress-spinner-theme($theme);
|
||||||
@include mat-radio-theme($theme);
|
@include mat-radio-theme($theme);
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
@import '../../input/input-theme';
|
@import '../../input/input-theme';
|
||||||
@import '../../list/list-theme';
|
@import '../../list/list-theme';
|
||||||
@import '../../menu/menu-theme';
|
@import '../../menu/menu-theme';
|
||||||
|
@import '../../paginator/paginator-theme';
|
||||||
@import '../../progress-bar/progress-bar-theme';
|
@import '../../progress-bar/progress-bar-theme';
|
||||||
@import '../../progress-spinner/progress-spinner-theme';
|
@import '../../progress-spinner/progress-spinner-theme';
|
||||||
@import '../../radio/radio-theme';
|
@import '../../radio/radio-theme';
|
||||||
@@ -42,6 +43,7 @@
|
|||||||
@include mat-icon-typography($config);
|
@include mat-icon-typography($config);
|
||||||
@include mat-input-typography($config);
|
@include mat-input-typography($config);
|
||||||
@include mat-menu-typography($config);
|
@include mat-menu-typography($config);
|
||||||
|
@include mat-paginator-typography($config);
|
||||||
@include mat-progress-bar-typography($config);
|
@include mat-progress-bar-typography($config);
|
||||||
@include mat-progress-spinner-typography($config);
|
@include mat-progress-spinner-typography($config);
|
||||||
@include mat-radio-typography($config);
|
@include mat-radio-typography($config);
|
||||||
|
|||||||
@@ -46,6 +46,7 @@ import {StyleModule} from './core/style/index';
|
|||||||
import {MdDatepickerModule} from './datepicker/index';
|
import {MdDatepickerModule} from './datepicker/index';
|
||||||
import {CdkDataTableModule} from './core/data-table/index';
|
import {CdkDataTableModule} from './core/data-table/index';
|
||||||
import {MdExpansionModule} from './expansion/index';
|
import {MdExpansionModule} from './expansion/index';
|
||||||
|
import {MdPaginatorModule} from './paginator/index';
|
||||||
|
|
||||||
const MATERIAL_MODULES = [
|
const MATERIAL_MODULES = [
|
||||||
MdAutocompleteModule,
|
MdAutocompleteModule,
|
||||||
@@ -62,6 +63,7 @@ const MATERIAL_MODULES = [
|
|||||||
MdInputModule,
|
MdInputModule,
|
||||||
MdListModule,
|
MdListModule,
|
||||||
MdMenuModule,
|
MdMenuModule,
|
||||||
|
MdPaginatorModule,
|
||||||
MdProgressBarModule,
|
MdProgressBarModule,
|
||||||
MdProgressSpinnerModule,
|
MdProgressSpinnerModule,
|
||||||
MdRadioModule,
|
MdRadioModule,
|
||||||
|
|||||||
@@ -0,0 +1,42 @@
|
|||||||
|
@import '../core/theming/palette';
|
||||||
|
@import '../core/theming/theming';
|
||||||
|
@import '../core/typography/typography-utils';
|
||||||
|
|
||||||
|
|
||||||
|
@mixin mat-paginator-theme($theme) {
|
||||||
|
$foreground: map-get($theme, foreground);
|
||||||
|
|
||||||
|
.mat-paginator,
|
||||||
|
.mat-paginator-page-size .mat-select-trigger {
|
||||||
|
color: mat-color($foreground, secondary-text);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-increment,
|
||||||
|
.mat-paginator-decrement {
|
||||||
|
border-top: 2px solid mat-color($foreground, 'icon');
|
||||||
|
border-right: 2px solid mat-color($foreground, 'icon');
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-icon-button[disabled] {
|
||||||
|
.mat-paginator-increment,
|
||||||
|
.mat-paginator-decrement {
|
||||||
|
border-color: mat-color($foreground, 'disabled');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@mixin mat-paginator-typography($config) {
|
||||||
|
.mat-paginator {
|
||||||
|
font: {
|
||||||
|
family: mat-font-family($config);
|
||||||
|
size: mat-font-size($config, caption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-page-size .mat-select-trigger {
|
||||||
|
font: {
|
||||||
|
family: mat-font-family($config);
|
||||||
|
size: mat-font-size($config, caption);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {NgModule} from '@angular/core';
|
||||||
|
import {CommonModule} from '@angular/common';
|
||||||
|
import {FormsModule} from '@angular/forms';
|
||||||
|
import {MdCommonModule, OverlayModule} from '../core';
|
||||||
|
import {MdButtonModule} from '../button/index';
|
||||||
|
import {MdSelectModule} from '../select/index';
|
||||||
|
import {MdPaginator} from './paginator';
|
||||||
|
import {MdPaginatorIntl} from './paginator-intl';
|
||||||
|
import {MdTooltipModule} from '../tooltip/index';
|
||||||
|
|
||||||
|
|
||||||
|
@NgModule({
|
||||||
|
imports: [
|
||||||
|
CommonModule,
|
||||||
|
FormsModule,
|
||||||
|
MdButtonModule,
|
||||||
|
MdSelectModule,
|
||||||
|
MdTooltipModule,
|
||||||
|
],
|
||||||
|
exports: [MdPaginator],
|
||||||
|
declarations: [MdPaginator],
|
||||||
|
providers: [MdPaginatorIntl],
|
||||||
|
})
|
||||||
|
export class MdPaginatorModule {}
|
||||||
|
|
||||||
|
|
||||||
|
export * from './paginator';
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {Injectable} from '@angular/core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To modify the labels and text displayed, create a new instance of MdPaginatorIntl and
|
||||||
|
* include it in a custom provider
|
||||||
|
*/
|
||||||
|
@Injectable()
|
||||||
|
export class MdPaginatorIntl {
|
||||||
|
/** A label for the page size selector. */
|
||||||
|
itemsPerPageLabel = 'Items per page:';
|
||||||
|
|
||||||
|
/** A label for the button that increments the current page. */
|
||||||
|
nextPageLabel = 'Next page';
|
||||||
|
|
||||||
|
/** A label for the button that decrements the current page. */
|
||||||
|
previousPageLabel = 'Previous page';
|
||||||
|
|
||||||
|
/** A label for the range of items within the current page and the length of the whole list. */
|
||||||
|
getRangeLabel = (page: number, pageSize: number, length: number) => {
|
||||||
|
if (length == 0 || pageSize == 0) { return `0 of ${length}`; }
|
||||||
|
|
||||||
|
length = Math.max(length, 0);
|
||||||
|
|
||||||
|
const startIndex = page * pageSize;
|
||||||
|
|
||||||
|
// If the start index exceeds the list length, do not try and fix the end index to the end.
|
||||||
|
const endIndex = startIndex < length ?
|
||||||
|
Math.min(startIndex + pageSize, length) :
|
||||||
|
startIndex + pageSize;
|
||||||
|
|
||||||
|
return `${startIndex + 1} - ${endIndex} of ${length}`;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<div class="mat-paginator-page-size">
|
||||||
|
<div class="mat-paginator-page-size-label">
|
||||||
|
{{_intl.itemsPerPageLabel}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<md-select *ngIf="_displayedPageSizeOptions.length > 1"
|
||||||
|
class="mat-paginator-page-size-select"
|
||||||
|
[ngModel]="pageSize"
|
||||||
|
[aria-label]="_intl.itemsPerPageLabel"
|
||||||
|
(change)="_changePageSize($event.value)">
|
||||||
|
<md-option *ngFor="let pageSizeOption of _displayedPageSizeOptions" [value]="pageSizeOption">
|
||||||
|
{{pageSizeOption}}
|
||||||
|
</md-option>
|
||||||
|
</md-select>
|
||||||
|
|
||||||
|
<div *ngIf="_displayedPageSizeOptions.length <= 1">{{pageSize}}</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<div class="mat-paginator-range-label">
|
||||||
|
{{_intl.getRangeLabel(pageIndex, pageSize, length)}}
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<button md-icon-button
|
||||||
|
class="mat-paginator-navigation-previous"
|
||||||
|
(click)="previousPage()"
|
||||||
|
[attr.aria-label]="_intl.previousPageLabel"
|
||||||
|
[mdTooltip]="_intl.previousPageLabel"
|
||||||
|
[mdTooltipPosition]="'above'"
|
||||||
|
[disabled]="!hasPreviousPage()">
|
||||||
|
<div class="mat-paginator-increment"></div>
|
||||||
|
</button>
|
||||||
|
<button md-icon-button
|
||||||
|
class="mat-paginator-navigation-next"
|
||||||
|
(click)="nextPage()"
|
||||||
|
[attr.aria-label]="_intl.nextPageLabel"
|
||||||
|
[mdTooltip]="_intl.nextPageLabel"
|
||||||
|
[mdTooltipPosition]="'above'"
|
||||||
|
[disabled]="!hasNextPage()">
|
||||||
|
<div class="mat-paginator-decrement"></div>
|
||||||
|
</button>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
`<md-paginator>` is a navigation for pages information, typically used with a data-table.
|
||||||
|
|
||||||
|
<!-- example(pagination-overview) -->
|
||||||
|
|
||||||
|
### Basic use
|
||||||
|
Each paginator instance requires:
|
||||||
|
* The number of items per page (default set to 50)
|
||||||
|
* The total number of items being paged
|
||||||
|
|
||||||
|
The current page index defaults to 0, but can be explicitly set via pageIndex.
|
||||||
|
|
||||||
|
When the user interacts with the paginator, a `PageEvent` will be fired that can be used to update
|
||||||
|
any associated data view.
|
||||||
|
|
||||||
|
### Page size options
|
||||||
|
The paginator displays a dropdown of page sizes for the user to choose from. The options for this
|
||||||
|
dropdown can be set via `pageSizeOptions`
|
||||||
|
|
||||||
|
The current pageSize will always appear in the dropdown, even if it is not included in pageSizeOptions.
|
||||||
|
|
||||||
|
### Internationalization
|
||||||
|
The labels for the paginator can be customized by providing your own instance of `MdPaginatorIntl`.
|
||||||
|
This will allow you to change the following:
|
||||||
|
1. The label for the length of each page.
|
||||||
|
2. The range text displayed to the user.
|
||||||
|
3. The tooltip messages on the navigation buttons.
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
$mat-paginator-height: 56px;
|
||||||
|
$mat-paginator-padding: 0 8px;
|
||||||
|
|
||||||
|
$mat-paginator-items-per-page-label-margin: 0 4px;
|
||||||
|
$mat-paginator-selector-margin: 0 4px;
|
||||||
|
$mat-paginator-selector-trigger-min-width: 56px;
|
||||||
|
|
||||||
|
$mat-paginator-range-label-margin: 0 32px;
|
||||||
|
|
||||||
|
$mat-paginator-button-margin: 8px;
|
||||||
|
$mat-paginator-button-icon-height: 8px;
|
||||||
|
$mat-paginator-button-icon-width: 8px;
|
||||||
|
|
||||||
|
$mat-paginator-button-decrement-icon-margin: 12px;
|
||||||
|
$mat-paginator-button-increment-icon-margin: 16px;
|
||||||
|
|
||||||
|
.mat-paginator {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: flex-end;
|
||||||
|
min-height: $mat-paginator-height;
|
||||||
|
padding: $mat-paginator-padding;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-page-size {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-page-size-label {
|
||||||
|
margin: $mat-paginator-items-per-page-label-margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-page-size-select {
|
||||||
|
margin: $mat-paginator-selector-margin;
|
||||||
|
|
||||||
|
.mat-select-trigger {
|
||||||
|
min-width: $mat-paginator-selector-trigger-min-width;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-range-label {
|
||||||
|
margin: $mat-paginator-range-label-margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-increment-button + .mat-paginator-increment-button {
|
||||||
|
margin: 0 0 0 $mat-paginator-button-margin;
|
||||||
|
|
||||||
|
[dir='rtl'] & {
|
||||||
|
margin: 0 $mat-paginator-button-margin 0 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-increment,
|
||||||
|
.mat-paginator-decrement {
|
||||||
|
width: $mat-paginator-button-icon-width;
|
||||||
|
height: $mat-paginator-button-icon-height;
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-decrement,
|
||||||
|
[dir='rtl'] .mat-paginator-increment {
|
||||||
|
transform: rotate(45deg);
|
||||||
|
}
|
||||||
|
.mat-paginator-increment,
|
||||||
|
[dir='rtl'] .mat-paginator-decrement {
|
||||||
|
transform: rotate(225deg);
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-decrement {
|
||||||
|
margin-left: $mat-paginator-button-decrement-icon-margin;
|
||||||
|
[dir='rtl'] & {
|
||||||
|
margin-right: $mat-paginator-button-decrement-icon-margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.mat-paginator-increment {
|
||||||
|
margin-left: $mat-paginator-button-increment-icon-margin;
|
||||||
|
[dir='rtl'] & {
|
||||||
|
margin-right: $mat-paginator-button-increment-icon-margin;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,279 @@
|
|||||||
|
import {async, ComponentFixture, TestBed} from '@angular/core/testing';
|
||||||
|
import {MdPaginatorModule} from './index';
|
||||||
|
import {MdPaginator, PageEvent} from './paginator';
|
||||||
|
import {Component, ElementRef, ViewChild} from '@angular/core';
|
||||||
|
import {MdPaginatorIntl} from './paginator-intl';
|
||||||
|
import {NoopAnimationsModule} from '@angular/platform-browser/animations';
|
||||||
|
import {customMatchers} from '../core/testing/jasmine-matchers';
|
||||||
|
import {dispatchMouseEvent} from '../core/testing/dispatch-events';
|
||||||
|
|
||||||
|
|
||||||
|
describe('MdPaginator', () => {
|
||||||
|
let fixture: ComponentFixture<MdPaginatorApp>;
|
||||||
|
let component: MdPaginatorApp;
|
||||||
|
let paginator: MdPaginator;
|
||||||
|
|
||||||
|
beforeEach(async(() => {
|
||||||
|
jasmine.addMatchers(customMatchers);
|
||||||
|
|
||||||
|
TestBed.configureTestingModule({
|
||||||
|
imports: [
|
||||||
|
MdPaginatorModule,
|
||||||
|
NoopAnimationsModule,
|
||||||
|
],
|
||||||
|
declarations: [
|
||||||
|
MdPaginatorApp,
|
||||||
|
MdPaginatorWithoutPageSizeApp,
|
||||||
|
MdPaginatorWithoutOptionsApp,
|
||||||
|
],
|
||||||
|
providers: [MdPaginatorIntl]
|
||||||
|
}).compileComponents();
|
||||||
|
|
||||||
|
fixture = TestBed.createComponent(MdPaginatorApp);
|
||||||
|
component = fixture.componentInstance;
|
||||||
|
paginator = component.mdPaginator;
|
||||||
|
|
||||||
|
fixture.detectChanges();
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('with the default internationalization provider', () => {
|
||||||
|
it('should show the right range text', () => {
|
||||||
|
const rangeElement = fixture.nativeElement.querySelector('.mat-paginator-range-label');
|
||||||
|
|
||||||
|
// View second page of list of 100, each page contains 10 items.
|
||||||
|
component.length = 100;
|
||||||
|
component.pageSize = 10;
|
||||||
|
component.pageIndex = 1;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(rangeElement.innerText).toBe('11 - 20 of 100');
|
||||||
|
|
||||||
|
// View third page of list of 200, each page contains 20 items.
|
||||||
|
component.length = 200;
|
||||||
|
component.pageSize = 20;
|
||||||
|
component.pageIndex = 2;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(rangeElement.innerText).toBe('41 - 60 of 200');
|
||||||
|
|
||||||
|
// View first page of list of 0, each page contains 5 items.
|
||||||
|
component.length = 0;
|
||||||
|
component.pageSize = 5;
|
||||||
|
component.pageIndex = 2;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(rangeElement.innerText).toBe('0 of 0');
|
||||||
|
|
||||||
|
// View third page of list of 12, each page contains 5 items.
|
||||||
|
component.length = 12;
|
||||||
|
component.pageSize = 5;
|
||||||
|
component.pageIndex = 2;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(rangeElement.innerText).toBe('11 - 12 of 12');
|
||||||
|
|
||||||
|
// View third page of list of 10, each page contains 5 items.
|
||||||
|
component.length = 10;
|
||||||
|
component.pageSize = 5;
|
||||||
|
component.pageIndex = 2;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(rangeElement.innerText).toBe('11 - 15 of 10');
|
||||||
|
|
||||||
|
// View third page of list of -5, each page contains 5 items.
|
||||||
|
component.length = -5;
|
||||||
|
component.pageSize = 5;
|
||||||
|
component.pageIndex = 2;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(rangeElement.innerText).toBe('11 - 15 of 0');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show right aria-labels for select and buttons', () => {
|
||||||
|
const select = fixture.nativeElement.querySelector('.mat-select');
|
||||||
|
expect(select.getAttribute('aria-label')).toBe('Items per page:');
|
||||||
|
|
||||||
|
const prevButton = fixture.nativeElement.querySelector('.mat-paginator-navigation-previous');
|
||||||
|
expect(prevButton.getAttribute('aria-label')).toBe('Previous page');
|
||||||
|
|
||||||
|
const nextButton = fixture.nativeElement.querySelector('.mat-paginator-navigation-next');
|
||||||
|
expect(nextButton.getAttribute('aria-label')).toBe('Next page');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when navigating with the navigation buttons', () => {
|
||||||
|
it('should be able to go to the next page', () => {
|
||||||
|
expect(paginator.pageIndex).toBe(0);
|
||||||
|
|
||||||
|
component.clickNextButton();
|
||||||
|
|
||||||
|
expect(paginator.pageIndex).toBe(1);
|
||||||
|
expect(component.latestPageEvent ? component.latestPageEvent.pageIndex : null).toBe(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to go to the previous page', () => {
|
||||||
|
paginator.pageIndex = 1;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(paginator.pageIndex).toBe(1);
|
||||||
|
|
||||||
|
component.clickPreviousButton();
|
||||||
|
|
||||||
|
expect(paginator.pageIndex).toBe(0);
|
||||||
|
expect(component.latestPageEvent ? component.latestPageEvent.pageIndex : null).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable navigating to the next page if at first page', () => {
|
||||||
|
component.goToLastPage();
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(paginator.pageIndex).toBe(10);
|
||||||
|
expect(paginator.hasNextPage()).toBe(false);
|
||||||
|
|
||||||
|
component.latestPageEvent = null;
|
||||||
|
component.clickNextButton();
|
||||||
|
|
||||||
|
expect(component.latestPageEvent).toBe(null);
|
||||||
|
expect(paginator.pageIndex).toBe(10);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should disable navigating to the previous page if at first page', () => {
|
||||||
|
expect(paginator.pageIndex).toBe(0);
|
||||||
|
expect(paginator.hasPreviousPage()).toBe(false);
|
||||||
|
|
||||||
|
component.latestPageEvent = null;
|
||||||
|
component.clickPreviousButton();
|
||||||
|
|
||||||
|
expect(component.latestPageEvent).toBe(null);
|
||||||
|
expect(paginator.pageIndex).toBe(0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should default the page size options to the page size if no options provided', () => {
|
||||||
|
const withoutOptionsAppFixture = TestBed.createComponent(MdPaginatorWithoutOptionsApp);
|
||||||
|
withoutOptionsAppFixture.detectChanges();
|
||||||
|
|
||||||
|
expect(withoutOptionsAppFixture.componentInstance.mdPaginator._displayedPageSizeOptions)
|
||||||
|
.toEqual([10]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show a sorted list of page size options including the current page size', () => {
|
||||||
|
expect(paginator._displayedPageSizeOptions).toEqual([5, 10, 25, 100]);
|
||||||
|
|
||||||
|
component.pageSize = 30;
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(paginator.pageSizeOptions).toEqual([5, 10, 25, 100]);
|
||||||
|
expect(paginator._displayedPageSizeOptions).toEqual([5, 10, 25, 30, 100]);
|
||||||
|
|
||||||
|
component.pageSizeOptions = [100, 25, 10, 5];
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(paginator._displayedPageSizeOptions).toEqual([5, 10, 25, 30, 100]);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should be able to change the page size while keeping the first item present', () => {
|
||||||
|
// Start on the third page of a list of 100 with a page size of 10.
|
||||||
|
component.pageIndex = 4;
|
||||||
|
component.pageSize = 10;
|
||||||
|
component.length = 100;
|
||||||
|
fixture.detectChanges();
|
||||||
|
|
||||||
|
// The first item of the page should be item with index 40
|
||||||
|
let firstPageItemIndex: number | null = paginator.pageIndex * paginator.pageSize;
|
||||||
|
expect(firstPageItemIndex).toBe(40);
|
||||||
|
|
||||||
|
// The first item on the page is now 25. Change the page size to 25 so that we should now be
|
||||||
|
// on the second page where the top item is index 25.
|
||||||
|
paginator._changePageSize(25);
|
||||||
|
let paginationEvent = component.latestPageEvent;
|
||||||
|
firstPageItemIndex = paginationEvent ?
|
||||||
|
paginationEvent.pageIndex * paginationEvent.pageSize : null;
|
||||||
|
expect(firstPageItemIndex).toBe(25);
|
||||||
|
expect(paginationEvent ? paginationEvent.pageIndex : null).toBe(1);
|
||||||
|
|
||||||
|
// The first item on the page is still 25. Change the page size to 8 so that we should now be
|
||||||
|
// on the fourth page where the top item is index 24.
|
||||||
|
paginator._changePageSize(8);
|
||||||
|
paginationEvent = component.latestPageEvent;
|
||||||
|
firstPageItemIndex = paginationEvent ?
|
||||||
|
paginationEvent.pageIndex * paginationEvent.pageSize : null;
|
||||||
|
expect(firstPageItemIndex).toBe(24);
|
||||||
|
expect(paginationEvent ? paginationEvent.pageIndex : null).toBe(3);
|
||||||
|
|
||||||
|
// The first item on the page is 24. Change the page size to 16 so that we should now be
|
||||||
|
// on the first page where the top item is index 0.
|
||||||
|
paginator._changePageSize(25);
|
||||||
|
paginationEvent = component.latestPageEvent;
|
||||||
|
firstPageItemIndex = paginationEvent ?
|
||||||
|
paginationEvent.pageIndex * paginationEvent.pageSize : null;
|
||||||
|
expect(firstPageItemIndex).toBe(0);
|
||||||
|
expect(paginationEvent ? paginationEvent.pageIndex : null).toBe(0);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should show a select only if there are multiple options', () => {
|
||||||
|
expect(paginator._displayedPageSizeOptions).toEqual([5, 10, 25, 100]);
|
||||||
|
expect(fixture.nativeElement.querySelector('.mat-select')).not.toBeNull();
|
||||||
|
|
||||||
|
// Remove options so that the paginator only uses the current page size (10) as an option.
|
||||||
|
// Should no longer show the select component since there is only one option.
|
||||||
|
component.pageSizeOptions = [];
|
||||||
|
fixture.detectChanges();
|
||||||
|
expect(fixture.nativeElement.querySelector('.mat-select')).toBeNull();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<md-paginator [pageIndex]="pageIndex"
|
||||||
|
[pageSize]="pageSize"
|
||||||
|
[pageSizeOptions]="pageSizeOptions"
|
||||||
|
[length]="length"
|
||||||
|
(page)="latestPageEvent = $event">
|
||||||
|
</md-paginator>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
class MdPaginatorApp {
|
||||||
|
pageIndex = 0;
|
||||||
|
pageSize = 10;
|
||||||
|
pageSizeOptions = [5, 10, 25, 100];
|
||||||
|
length = 100;
|
||||||
|
|
||||||
|
latestPageEvent: PageEvent | null;
|
||||||
|
|
||||||
|
@ViewChild(MdPaginator) mdPaginator: MdPaginator;
|
||||||
|
|
||||||
|
constructor(private _elementRef: ElementRef) { }
|
||||||
|
|
||||||
|
clickPreviousButton() {
|
||||||
|
const previousButton =
|
||||||
|
this._elementRef.nativeElement.querySelector('.mat-paginator-navigation-previous');
|
||||||
|
dispatchMouseEvent(previousButton, 'click');
|
||||||
|
}
|
||||||
|
|
||||||
|
clickNextButton() {
|
||||||
|
const nextButton =
|
||||||
|
this._elementRef.nativeElement.querySelector('.mat-paginator-navigation-next');
|
||||||
|
dispatchMouseEvent(nextButton, 'click'); }
|
||||||
|
|
||||||
|
goToLastPage() {
|
||||||
|
this.pageIndex = Math.ceil(this.length / this.pageSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<md-paginator [length]="100"></md-paginator>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
class MdPaginatorWithoutPageSizeOrOptionsApp {
|
||||||
|
@ViewChild(MdPaginator) mdPaginator: MdPaginator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<md-paginator [pageSizeOptions]="[10, 20, 30]"></md-paginator>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
class MdPaginatorWithoutPageSizeApp {
|
||||||
|
@ViewChild(MdPaginator) mdPaginator: MdPaginator;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
template: `
|
||||||
|
<md-paginator [pageSize]="10"></md-paginator>
|
||||||
|
`,
|
||||||
|
})
|
||||||
|
class MdPaginatorWithoutOptionsApp {
|
||||||
|
@ViewChild(MdPaginator) mdPaginator: MdPaginator;
|
||||||
|
}
|
||||||
@@ -0,0 +1,157 @@
|
|||||||
|
/**
|
||||||
|
* @license
|
||||||
|
* Copyright Google Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* Use of this source code is governed by an MIT-style license that can be
|
||||||
|
* found in the LICENSE file at https://angular.io/license
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
ChangeDetectionStrategy,
|
||||||
|
Component,
|
||||||
|
EventEmitter,
|
||||||
|
Input,
|
||||||
|
OnInit,
|
||||||
|
Output,
|
||||||
|
ViewEncapsulation
|
||||||
|
} from '@angular/core';
|
||||||
|
import {MdPaginatorIntl} from './paginator-intl';
|
||||||
|
import {MATERIAL_COMPATIBILITY_MODE} from '../core';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Change event object that is emitted when the user selects a
|
||||||
|
* different page size or navigates to another page.
|
||||||
|
*/
|
||||||
|
export class PageEvent {
|
||||||
|
pageIndex: number;
|
||||||
|
pageSize: number;
|
||||||
|
length: number;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Component to provide navigation between paged information. Displays the size of the current
|
||||||
|
* page, user-selectable options to change that size, what items are being shown, and
|
||||||
|
* navigational button to go to the previous or next page.
|
||||||
|
*/
|
||||||
|
@Component({
|
||||||
|
moduleId: module.id,
|
||||||
|
selector: 'md-paginator, mat-paginator',
|
||||||
|
templateUrl: 'paginator.html',
|
||||||
|
styleUrls: ['paginator.css'],
|
||||||
|
host: {
|
||||||
|
'class': 'mat-paginator',
|
||||||
|
},
|
||||||
|
providers: [
|
||||||
|
{provide: MATERIAL_COMPATIBILITY_MODE, useValue: false}
|
||||||
|
],
|
||||||
|
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||||
|
encapsulation: ViewEncapsulation.None,
|
||||||
|
})
|
||||||
|
export class MdPaginator implements OnInit {
|
||||||
|
private _initialized: boolean;
|
||||||
|
|
||||||
|
/** The zero-based page index of the displayed list of items. Defaulted to 0. */
|
||||||
|
@Input() pageIndex: number = 0;
|
||||||
|
|
||||||
|
/** The length of the total number of items that are being paginated. Defaulted to 0. */
|
||||||
|
@Input() length: number = 0;
|
||||||
|
|
||||||
|
/** Number of items to display on a page. By default set to 50. */
|
||||||
|
@Input()
|
||||||
|
get pageSize(): number { return this._pageSize; }
|
||||||
|
set pageSize(pageSize: number) {
|
||||||
|
this._pageSize = pageSize;
|
||||||
|
this._updateDisplayedPageSizeOptions();
|
||||||
|
}
|
||||||
|
private _pageSize: number = 50;
|
||||||
|
|
||||||
|
/** The set of provided page size options to display to the user. */
|
||||||
|
@Input()
|
||||||
|
get pageSizeOptions(): number[] { return this._pageSizeOptions; }
|
||||||
|
set pageSizeOptions(pageSizeOptions: number[]) {
|
||||||
|
this._pageSizeOptions = pageSizeOptions;
|
||||||
|
this._updateDisplayedPageSizeOptions();
|
||||||
|
}
|
||||||
|
private _pageSizeOptions: number[] = [];
|
||||||
|
|
||||||
|
/** Event emitted when the paginator changes the page size or page index. */
|
||||||
|
@Output() page = new EventEmitter<PageEvent>();
|
||||||
|
|
||||||
|
/** Displayed set of page size options. Will be sorted and include current page size. */
|
||||||
|
_displayedPageSizeOptions: number[];
|
||||||
|
|
||||||
|
constructor(public _intl: MdPaginatorIntl) { }
|
||||||
|
|
||||||
|
ngOnInit() {
|
||||||
|
this._initialized = true;
|
||||||
|
this._updateDisplayedPageSizeOptions();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Increments the page index to the next page index if a next page exists. */
|
||||||
|
nextPage() {
|
||||||
|
if (!this.hasNextPage()) { return; }
|
||||||
|
this.pageIndex++;
|
||||||
|
this._emitPageEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Decrements the page index to the previous page index if a next page exists. */
|
||||||
|
previousPage() {
|
||||||
|
if (!this.hasPreviousPage()) { return; }
|
||||||
|
this.pageIndex--;
|
||||||
|
this._emitPageEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns true if the user can go to the next page. */
|
||||||
|
hasPreviousPage() {
|
||||||
|
return this.pageIndex >= 1 && this.pageSize != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Returns true if the user can go to the next page. */
|
||||||
|
hasNextPage() {
|
||||||
|
const numberOfPages = Math.ceil(this.length / this.pageSize) - 1;
|
||||||
|
return this.pageIndex < numberOfPages && this.pageSize != 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Changes the page size so that the first item displayed on the page will still be
|
||||||
|
* displayed using the new page size.
|
||||||
|
*
|
||||||
|
* For example, if the page size is 10 and on the second page (items indexed 10-19) then
|
||||||
|
* switching so that the page size is 5 will set the third page as the current page so
|
||||||
|
* that the 10th item will still be displayed.
|
||||||
|
*/
|
||||||
|
_changePageSize(pageSize: number) {
|
||||||
|
// Current page needs to be updated to reflect the new page size. Navigate to the page
|
||||||
|
// containing the previous page's first item.
|
||||||
|
const startIndex = this.pageIndex * this.pageSize;
|
||||||
|
this.pageIndex = Math.floor(startIndex / pageSize) || 0;
|
||||||
|
|
||||||
|
this.pageSize = pageSize;
|
||||||
|
this._emitPageEvent();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
private _updateDisplayedPageSizeOptions() {
|
||||||
|
if (!this._initialized) { return; }
|
||||||
|
|
||||||
|
this._displayedPageSizeOptions = this.pageSizeOptions.slice();
|
||||||
|
if (this._displayedPageSizeOptions.indexOf(this.pageSize) == -1) {
|
||||||
|
this._displayedPageSizeOptions.push(this.pageSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Sort the numbers using a number-specific sort function.
|
||||||
|
this._displayedPageSizeOptions.sort((a, b) => a - b);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Emits an event notifying that a change of the paginator's properties has been triggered. */
|
||||||
|
private _emitPageEvent() {
|
||||||
|
this.page.next({
|
||||||
|
pageIndex: this.pageIndex,
|
||||||
|
pageSize: this.pageSize,
|
||||||
|
length: this.length
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,7 @@ export * from './icon/index';
|
|||||||
export * from './input/index';
|
export * from './input/index';
|
||||||
export * from './list/index';
|
export * from './list/index';
|
||||||
export * from './menu/index';
|
export * from './menu/index';
|
||||||
|
export * from './paginator/index';
|
||||||
export * from './progress-bar/index';
|
export * from './progress-bar/index';
|
||||||
export * from './progress-spinner/index';
|
export * from './progress-spinner/index';
|
||||||
export * from './radio/index';
|
export * from './radio/index';
|
||||||
|
|||||||
@@ -15,8 +15,8 @@ import {
|
|||||||
ProgressBarConfigurableExample
|
ProgressBarConfigurableExample
|
||||||
} from './progress-bar-configurable/progress-bar-configurable-example';
|
} from './progress-bar-configurable/progress-bar-configurable-example';
|
||||||
import {
|
import {
|
||||||
DialogOverviewExampleDialog,
|
DialogOverviewExample,
|
||||||
DialogOverviewExample
|
DialogOverviewExampleDialog
|
||||||
} from './dialog-overview/dialog-overview-example';
|
} from './dialog-overview/dialog-overview-example';
|
||||||
import {RadioNgModelExample} from './radio-ng-model/radio-ng-model-example';
|
import {RadioNgModelExample} from './radio-ng-model/radio-ng-model-example';
|
||||||
import {CardFancyExample} from './card-fancy/card-fancy-example';
|
import {CardFancyExample} from './card-fancy/card-fancy-example';
|
||||||
@@ -36,12 +36,12 @@ import {
|
|||||||
import {ListSectionsExample} from './list-sections/list-sections-example';
|
import {ListSectionsExample} from './list-sections/list-sections-example';
|
||||||
import {SnackBarOverviewExample} from './snack-bar-overview/snack-bar-overview-example';
|
import {SnackBarOverviewExample} from './snack-bar-overview/snack-bar-overview-example';
|
||||||
import {
|
import {
|
||||||
DialogResultExampleDialog,
|
DialogResultExample,
|
||||||
DialogResultExample
|
DialogResultExampleDialog
|
||||||
} from './dialog-result/dialog-result-example';
|
} from './dialog-result/dialog-result-example';
|
||||||
import {
|
import {
|
||||||
DialogElementsExampleDialog,
|
DialogElementsExample,
|
||||||
DialogElementsExample
|
DialogElementsExampleDialog
|
||||||
} from './dialog-elements/dialog-elements-example';
|
} from './dialog-elements/dialog-elements-example';
|
||||||
import {TooltipOverviewExample} from './tooltip-overview/tooltip-overview-example';
|
import {TooltipOverviewExample} from './tooltip-overview/tooltip-overview-example';
|
||||||
import {ButtonToggleOverviewExample} from './button-toggle-overview/button-toggle-overview-example';
|
import {ButtonToggleOverviewExample} from './button-toggle-overview/button-toggle-overview-example';
|
||||||
@@ -68,20 +68,22 @@ import {SelectOverviewExample} from './select-overview/select-overview-example';
|
|||||||
import {ChipsOverviewExample} from './chips-overview/chips-overview-example';
|
import {ChipsOverviewExample} from './chips-overview/chips-overview-example';
|
||||||
import {ChipsStackedExample} from './chips-stacked/chips-stacked-example';
|
import {ChipsStackedExample} from './chips-stacked/chips-stacked-example';
|
||||||
import {SelectFormExample} from './select-form/select-form-example';
|
import {SelectFormExample} from './select-form/select-form-example';
|
||||||
|
import {PaginatorOverviewExample} from './paginator-overview/paginator-overview-example';
|
||||||
import {DatepickerOverviewExample} from './datepicker-overview/datepicker-overview-example';
|
import {DatepickerOverviewExample} from './datepicker-overview/datepicker-overview-example';
|
||||||
|
import {
|
||||||
|
PaginatorConfigurableExample
|
||||||
|
} from './paginator-configurable/paginator-configurable-example';
|
||||||
import {InputOverviewExample} from './input-overview/input-overview-example';
|
import {InputOverviewExample} from './input-overview/input-overview-example';
|
||||||
import {InputErrorsExample} from './input-errors/input-errors-example';
|
import {InputErrorsExample} from './input-errors/input-errors-example';
|
||||||
import {InputFormExample} from './input-form/input-form-example';
|
import {InputFormExample} from './input-form/input-form-example';
|
||||||
import {InputPrefixSuffixExample} from './input-prefix-suffix/input-prefix-suffix-example';
|
import {InputPrefixSuffixExample} from './input-prefix-suffix/input-prefix-suffix-example';
|
||||||
import {InputHintExample} from './input-hint/input-hint-example';
|
import {InputHintExample} from './input-hint/input-hint-example';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
MdAutocompleteModule, MdButtonModule, MdButtonToggleModule, MdCardModule, MdCheckboxModule,
|
MdAutocompleteModule, MdButtonModule, MdButtonToggleModule, MdCardModule, MdCheckboxModule,
|
||||||
MdChipsModule, MdDatepickerModule, MdDialogModule, MdGridListModule, MdIconModule, MdInputModule,
|
MdChipsModule, MdDatepickerModule, MdDialogModule, MdGridListModule, MdIconModule, MdInputModule,
|
||||||
MdListModule, MdMenuModule, MdProgressBarModule, MdProgressSpinnerModule, MdRadioModule,
|
MdListModule, MdMenuModule, MdPaginatorModule, MdProgressBarModule, MdProgressSpinnerModule,
|
||||||
MdSelectModule, MdSidenavModule, MdSliderModule, MdSlideToggleModule, MdSnackBarModule,
|
MdRadioModule, MdSelectModule, MdSidenavModule, MdSliderModule, MdSlideToggleModule,
|
||||||
MdTabsModule,
|
MdSnackBarModule, MdTabsModule, MdToolbarModule, MdTooltipModule
|
||||||
MdToolbarModule, MdTooltipModule
|
|
||||||
} from '@angular/material';
|
} from '@angular/material';
|
||||||
|
|
||||||
export interface LiveExample {
|
export interface LiveExample {
|
||||||
@@ -143,6 +145,11 @@ export const EXAMPLE_COMPONENTS = {
|
|||||||
'list-sections': {title: 'List with sections', component: ListSectionsExample},
|
'list-sections': {title: 'List with sections', component: ListSectionsExample},
|
||||||
'menu-icons': {title: 'Menu with icons', component: MenuIconsExample},
|
'menu-icons': {title: 'Menu with icons', component: MenuIconsExample},
|
||||||
'menu-overview': {title: 'Basic menu', component: MenuOverviewExample},
|
'menu-overview': {title: 'Basic menu', component: MenuOverviewExample},
|
||||||
|
'paginator-overview': {title: 'Paginator', component: PaginatorOverviewExample},
|
||||||
|
'paginator-configurable': {
|
||||||
|
title: 'Configurable paginator',
|
||||||
|
component: PaginatorConfigurableExample
|
||||||
|
},
|
||||||
'progress-bar-configurable': {
|
'progress-bar-configurable': {
|
||||||
title: 'Configurable progress-bar',
|
title: 'Configurable progress-bar',
|
||||||
component: ProgressBarConfigurableExample
|
component: ProgressBarConfigurableExample
|
||||||
@@ -201,6 +208,7 @@ export const EXAMPLE_COMPONENTS = {
|
|||||||
MdInputModule,
|
MdInputModule,
|
||||||
MdListModule,
|
MdListModule,
|
||||||
MdMenuModule,
|
MdMenuModule,
|
||||||
|
MdPaginatorModule,
|
||||||
MdProgressBarModule,
|
MdProgressBarModule,
|
||||||
MdProgressSpinnerModule,
|
MdProgressSpinnerModule,
|
||||||
MdRadioModule,
|
MdRadioModule,
|
||||||
@@ -252,6 +260,7 @@ export const EXAMPLE_LIST = [
|
|||||||
ListSectionsExample,
|
ListSectionsExample,
|
||||||
MenuIconsExample,
|
MenuIconsExample,
|
||||||
MenuOverviewExample,
|
MenuOverviewExample,
|
||||||
|
PaginatorOverviewExample,
|
||||||
ProgressBarConfigurableExample,
|
ProgressBarConfigurableExample,
|
||||||
ProgressBarOverviewExample,
|
ProgressBarOverviewExample,
|
||||||
ProgressSpinnerConfigurableExample,
|
ProgressSpinnerConfigurableExample,
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
/** No CSS for this example */
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<md-input-container>
|
||||||
|
List length:
|
||||||
|
<input mdInput [(ngModel)]="length">
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
<md-input-container>
|
||||||
|
Page size:
|
||||||
|
<input mdInput [(ngModel)]="pageSize">
|
||||||
|
</md-input-container>
|
||||||
|
<md-input-container>
|
||||||
|
Page size options:
|
||||||
|
<input mdInput
|
||||||
|
[ngModel]="pageSizeOptions"
|
||||||
|
(ngModelChange)="setPageSizeOptions($event)">
|
||||||
|
</md-input-container>
|
||||||
|
|
||||||
|
<md-paginator [length]="length"
|
||||||
|
[pageSize]="pageSize"
|
||||||
|
[pageSizeOptions]="pageSizeOptions"
|
||||||
|
(page)="pageEvent = $event">
|
||||||
|
</md-paginator>
|
||||||
|
|
||||||
|
<div *ngIf="pageEvent">
|
||||||
|
<h2>Page Change Event Properties</h2>
|
||||||
|
<div>List length: {{pageEvent.length}}</div>
|
||||||
|
<div>Page size: {{pageEvent.pageSize}}</div>
|
||||||
|
<div>Page index: {{pageEvent.pageIndex}}</div>
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,20 @@
|
|||||||
|
import {Component} from '@angular/core';
|
||||||
|
import {PageEvent} from '@angular/material';
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'paginator-configurable-example',
|
||||||
|
templateUrl: 'paginator-configurable-example.html',
|
||||||
|
})
|
||||||
|
export class PaginatorConfigurableExample {
|
||||||
|
// MdPaginator Inputs
|
||||||
|
length = 100;
|
||||||
|
pageSize = 10;
|
||||||
|
pageSizeOptions = [5, 10, 25, 100];
|
||||||
|
|
||||||
|
// MdPaginator Output
|
||||||
|
pageEvent: PageEvent;
|
||||||
|
|
||||||
|
setPageSizeOptions(setPageSizeOptionsInput: string) {
|
||||||
|
this.pageSizeOptions = setPageSizeOptionsInput.split(',').map(str => +str);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
/** No CSS for this example */
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<md-paginator [length]="100"
|
||||||
|
[pageSize]="10"
|
||||||
|
[pageSizeOptions]="[5, 10, 25, 100]" ]>
|
||||||
|
</md-paginator>
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
import {Component} from '@angular/core';
|
||||||
|
|
||||||
|
|
||||||
|
@Component({
|
||||||
|
selector: 'paginator-overview-example',
|
||||||
|
templateUrl: 'paginator-overview-example.html',
|
||||||
|
})
|
||||||
|
export class PaginatorOverviewExample {}
|
||||||
@@ -97,6 +97,7 @@ let apiDocsPackage = new DgeniPackage('material2-api-docs', dgeniPackageDeps)
|
|||||||
'input/index.ts',
|
'input/index.ts',
|
||||||
'list/index.ts',
|
'list/index.ts',
|
||||||
'menu/index.ts',
|
'menu/index.ts',
|
||||||
|
'paginator/index.ts',
|
||||||
'progress-bar/index.ts',
|
'progress-bar/index.ts',
|
||||||
'progress-spinner/index.ts',
|
'progress-spinner/index.ts',
|
||||||
'radio/index.ts',
|
'radio/index.ts',
|
||||||
|
|||||||
Reference in New Issue
Block a user