Skip to content

Commit

Permalink
feat(paginator): default page size to first option (#5822)
Browse files Browse the repository at this point in the history
* feat(paginator): default page size to first option

* resolve change detection issue

* add test for the change detect

* revert demo
  • Loading branch information
andrewseguin authored Jul 25, 2017
1 parent 388494f commit 42c50b6
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 27 deletions.
2 changes: 1 addition & 1 deletion src/demo-app/table/table-demo.html
Original file line number Diff line number Diff line change
Expand Up @@ -139,4 +139,4 @@ <h3>MdTable Example</h3>
[length]="_peopleDatabase.data.length"
[pageSizeOptions]="[5, 10, 25, 100]">
</md-paginator>
</div>
</div>
80 changes: 59 additions & 21 deletions src/lib/paginator/paginator.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,16 +22,19 @@ describe('MdPaginator', () => {
MdPaginatorApp,
MdPaginatorWithoutPageSizeApp,
MdPaginatorWithoutOptionsApp,
MdPaginatorWithoutInputsApp,
],
providers: [MdPaginatorIntl]
}).compileComponents();
}));

beforeEach(() => {
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', () => {
Expand Down Expand Up @@ -84,19 +87,16 @@ describe('MdPaginator', () => {
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');
expect(getPreviousButton(fixture).getAttribute('aria-label')).toBe('Previous page');
expect(getNextButton(fixture).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();
dispatchMouseEvent(getNextButton(fixture), 'click');

expect(paginator.pageIndex).toBe(1);
expect(component.latestPageEvent ? component.latestPageEvent.pageIndex : null).toBe(1);
Expand All @@ -107,7 +107,7 @@ describe('MdPaginator', () => {
fixture.detectChanges();
expect(paginator.pageIndex).toBe(1);

component.clickPreviousButton();
dispatchMouseEvent(getPreviousButton(fixture), 'click');

expect(paginator.pageIndex).toBe(0);
expect(component.latestPageEvent ? component.latestPageEvent.pageIndex : null).toBe(0);
Expand All @@ -120,7 +120,7 @@ describe('MdPaginator', () => {
expect(paginator.hasNextPage()).toBe(false);

component.latestPageEvent = null;
component.clickNextButton();
dispatchMouseEvent(getNextButton(fixture), 'click');

expect(component.latestPageEvent).toBe(null);
expect(paginator.pageIndex).toBe(10);
Expand All @@ -131,13 +131,38 @@ describe('MdPaginator', () => {
expect(paginator.hasPreviousPage()).toBe(false);

component.latestPageEvent = null;
component.clickPreviousButton();
dispatchMouseEvent(getPreviousButton(fixture), 'click');

expect(component.latestPageEvent).toBe(null);
expect(paginator.pageIndex).toBe(0);
});
});

it('should mark for check when inputs are changed directly', () => {
const rangeElement = fixture.nativeElement.querySelector('.mat-paginator-range-label');

expect(rangeElement.innerText).toBe('1 - 10 of 100');

paginator.length = 99;
fixture.detectChanges();
expect(rangeElement.innerText).toBe('1 - 10 of 99');

paginator.pageSize = 6;
fixture.detectChanges();
expect(rangeElement.innerText).toBe('1 - 6 of 99');

paginator.pageIndex = 1;
fixture.detectChanges();
expect(rangeElement.innerText).toBe('7 - 12 of 99');

// Having one option and the same page size should remove the select menu
expect(fixture.nativeElement.querySelector('.mat-select')).not.toBeNull();
paginator.pageSize = 10;
paginator.pageSizeOptions = [10];
fixture.detectChanges();
expect(fixture.nativeElement.querySelector('.mat-select')).toBeNull();
});

it('should default the page size options to the page size if no options provided', () => {
const withoutOptionsAppFixture = TestBed.createComponent(MdPaginatorWithoutOptionsApp);
withoutOptionsAppFixture.detectChanges();
Expand All @@ -146,6 +171,13 @@ describe('MdPaginator', () => {
.toEqual([10]);
});

it('should default the page size to the first page size option if not provided', () => {
const withoutPageSizeAppFixture = TestBed.createComponent(MdPaginatorWithoutPageSizeApp);
withoutPageSizeAppFixture.detectChanges();

expect(withoutPageSizeAppFixture.componentInstance.mdPaginator.pageSize).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]);

Expand Down Expand Up @@ -210,6 +242,14 @@ describe('MdPaginator', () => {
});
});

function getPreviousButton(fixture: ComponentFixture<any>) {
return fixture.nativeElement.querySelector('.mat-paginator-navigation-previous');
}

function getNextButton(fixture: ComponentFixture<any>) {
return fixture.nativeElement.querySelector('.mat-paginator-navigation-next');
}

@Component({
template: `
<md-paginator [pageIndex]="pageIndex"
Expand All @@ -232,22 +272,20 @@ class MdPaginatorApp {

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></md-paginator>
`,
})
class MdPaginatorWithoutInputsApp {
@ViewChild(MdPaginator) mdPaginator: MdPaginator;
}

@Component({
template: `
<md-paginator [pageSizeOptions]="[10, 20, 30]"></md-paginator>
Expand Down
35 changes: 30 additions & 5 deletions src/lib/paginator/paginator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
*/

import {
ChangeDetectionStrategy,
ChangeDetectionStrategy, ChangeDetectorRef,
Component,
EventEmitter,
Input,
Expand All @@ -18,6 +18,9 @@ import {
import {MdPaginatorIntl} from './paginator-intl';
import {MATERIAL_COMPATIBILITY_MODE} from '../core';

/** The default page size if there is no page size and there are no provided page size options. */
const DEFAULT_PAGE_SIZE = 50;

/**
* Change event object that is emitted when the user selects a
* different page size or navigates to another page.
Expand Down Expand Up @@ -56,10 +59,22 @@ 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;
@Input()
get pageIndex(): number { return this._pageIndex; }
set pageIndex(pageIndex: number) {
this._pageIndex = pageIndex;
this._changeDetectorRef.markForCheck();
}
_pageIndex: number = 0;

/** The length of the total number of items that are being paginated. Defaulted to 0. */
@Input() length: number = 0;
@Input()
get length(): number { return this._length; }
set length(length: number) {
this._length = length;
this._changeDetectorRef.markForCheck();
}
_length: number = 0;

/** Number of items to display on a page. By default set to 50. */
@Input()
Expand All @@ -68,7 +83,7 @@ export class MdPaginator implements OnInit {
this._pageSize = pageSize;
this._updateDisplayedPageSizeOptions();
}
private _pageSize: number = 50;
private _pageSize: number;

/** The set of provided page size options to display to the user. */
@Input()
Expand All @@ -85,7 +100,8 @@ export class MdPaginator implements OnInit {
/** Displayed set of page size options. Will be sorted and include current page size. */
_displayedPageSizeOptions: number[];

constructor(public _intl: MdPaginatorIntl) { }
constructor(public _intl: MdPaginatorIntl,
private _changeDetectorRef: ChangeDetectorRef) { }

ngOnInit() {
this._initialized = true;
Expand Down Expand Up @@ -142,13 +158,22 @@ export class MdPaginator implements OnInit {
private _updateDisplayedPageSizeOptions() {
if (!this._initialized) { return; }

// If no page size is provided, use the first page size option or the default page size.
if (!this.pageSize) {
this._pageSize = this.pageSizeOptions.length != 0 ?
this.pageSizeOptions[0] :
DEFAULT_PAGE_SIZE;
}

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);

this._changeDetectorRef.markForCheck();
}

/** Emits an event notifying that a change of the paginator's properties has been triggered. */
Expand Down

0 comments on commit 42c50b6

Please sign in to comment.