Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix(material/paginator): fix issue with paginator focus #29006

Open
wants to merge 6 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 44 additions & 0 deletions src/material/paginator/paginator.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,7 @@ let nextUniqueId = 0;
host: {
'class': 'mat-mdc-paginator',
'role': 'group',
'(keydown)': '_focusPreviousOrNextIfDisabled($event)',
},
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
Expand All @@ -118,6 +119,12 @@ export class MatPaginator implements OnInit, OnDestroy {
/** ID for the DOM node containing the paginator's items per page label. */
readonly _pageSizeLabelId = `mat-paginator-page-size-label-${nextUniqueId++}`;

/** MDC class names of paginator buttons. */
readonly _pageNext = 'mat-mdc-paginator-navigation-next';
readonly _pagePrevious = 'mat-mdc-paginator-navigation-previous';
readonly _pageFirst = 'mat-mdc-paginator-navigation-first';
readonly _pageLast = 'mat-mdc-paginator-navigation-last';

private _intlChanges: Subscription;
private _isInitialized = false;
private _initializedStream = new ReplaySubject<void>(1);
Expand Down Expand Up @@ -300,6 +307,43 @@ export class MatPaginator implements OnInit, OnDestroy {
return Math.ceil(this.length / this.pageSize);
}

/**
* Handle keyboard Enter event for the Paginator. Keeps focus on appropriate paginator button
* whenever next, previous, first, or last button becomes disabled.
* @param event The keyboard event to be handled.
*/
_focusPreviousOrNextIfDisabled(event: KeyboardEvent) {
if (event.key === 'Enter') {
const currentElement = event.target as HTMLButtonElement;

/**
* setTimeout is used to give DOM time to update currentElement (paginator buttons)
* to see if it's disabled or not.
*/
setTimeout(() => {
event.preventDefault();
if (currentElement.disabled && currentElement.classList.contains(this._pageNext)) {
const previousElement = currentElement.previousElementSibling as HTMLButtonElement;
previousElement?.focus();
} else if (
currentElement.disabled &&
currentElement.classList.contains(this._pagePrevious)
) {
const nextElement = currentElement.nextElementSibling as HTMLButtonElement;
nextElement?.focus();
} else if (currentElement.disabled && currentElement.classList.contains(this._pageFirst)) {
const nextElement = currentElement.nextElementSibling
?.nextElementSibling as HTMLButtonElement;
nextElement?.focus();
} else if (currentElement.disabled && currentElement.classList.contains(this._pageLast)) {
const previousElement = currentElement.previousElementSibling
?.previousElementSibling as HTMLButtonElement;
previousElement?.focus();
}
}, 100);
}
}

/**
* Changes the page size so that the first item displayed on the page will still be
* displayed using the new page size.
Expand Down
8 changes: 8 additions & 0 deletions tools/public_api_guard/material/paginator.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ export class MatPaginator implements OnInit, OnDestroy {
disabled: boolean;
_displayedPageSizeOptions: number[];
firstPage(): void;
_focusPreviousOrNextIfDisabled(event: KeyboardEvent): void;
_formFieldAppearance?: MatFormFieldAppearance;
getNumberOfPages(): number;
hasNextPage(): boolean;
Expand Down Expand Up @@ -70,8 +71,15 @@ export class MatPaginator implements OnInit, OnDestroy {
// (undocumented)
ngOnInit(): void;
readonly page: EventEmitter<PageEvent>;
// (undocumented)
readonly _pageFirst = "mat-mdc-paginator-navigation-first";
get pageIndex(): number;
set pageIndex(value: number);
// (undocumented)
readonly _pageLast = "mat-mdc-paginator-navigation-last";
readonly _pageNext = "mat-mdc-paginator-navigation-next";
// (undocumented)
readonly _pagePrevious = "mat-mdc-paginator-navigation-previous";
get pageSize(): number;
set pageSize(value: number);
readonly _pageSizeLabelId: string;
Expand Down
Loading