Skip to content

Commit b67f9b6

Browse files
authored
Merge pull request #16668 from IgniteUI/vtoneva/fix-accesibility-in-paginator
fix(paginator): accessibility issues in Paginator Component
2 parents 537702c + 8fd3a11 commit b67f9b6

6 files changed

Lines changed: 41 additions & 8 deletions

File tree

projects/igniteui-angular/paginator/src/paginator/page-size-selector.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
<label class="igx-page-size__label">{{ paginator.resourceStrings.igx_paginator_label }}</label>
1+
<label [id]="labelId" class="igx-page-size__label">{{ paginator.resourceStrings.igx_paginator_label }}</label>
22
<div class="igx-page-size__select">
3-
<igx-select [overlaySettings]="paginator.overlaySettings" [(ngModel)]="paginator.perPage" type="border">
3+
<igx-select [labelledBy]="labelId" [overlaySettings]="paginator.overlaySettings" [(ngModel)]="paginator.perPage" type="border">
44
@for (val of paginator.selectOptions; track val) {
55
<igx-select-item [value]="val">
66
{{ val }}

projects/igniteui-angular/paginator/src/paginator/pager.component.html

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
<button
22
[title]="paginator.resourceStrings.igx_paginator_first_page_button_text"
3+
[attr.aria-label]="paginator.resourceStrings.igx_paginator_first_page_button_text"
34
[disabled]="paginator.isFirstPage"
45
[attr.aria-disabled]="paginator.isFirstPage"
56
(click)="paginator.paginate(0)"
@@ -12,6 +13,7 @@
1213
</button>
1314
<button
1415
[title]="paginator.resourceStrings.igx_paginator_previous_page_button_text"
16+
[attr.aria-label]="paginator.resourceStrings.igx_paginator_previous_page_button_text"
1517
[disabled]="paginator.isFirstPage"
1618
[attr.aria-disabled]="paginator.isFirstPage"
1719
(click)="paginator.previousPage()"
@@ -33,6 +35,7 @@
3335
</div>
3436
<button
3537
[title]="paginator.resourceStrings.igx_paginator_next_page_button_text"
38+
[attr.aria-label]="paginator.resourceStrings.igx_paginator_next_page_button_text"
3639
[disabled]="paginator.isLastPage"
3740
[attr.aria-disabled]="paginator.isLastPage"
3841
(click)="paginator.nextPage()"
@@ -45,6 +48,7 @@
4548
</button>
4649
<button
4750
[title]="paginator.resourceStrings.igx_paginator_last_page_button_text"
51+
[attr.aria-label]="paginator.resourceStrings.igx_paginator_last_page_button_text"
4852
[disabled]="paginator.isLastPage"
4953
[attr.aria-disabled]="paginator.isLastPage"
5054
(click)="paginator.paginate(paginator.totalPages - 1)"

projects/igniteui-angular/paginator/src/paginator/paginator.component.spec.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -277,6 +277,26 @@ describe('IgxPaginator with custom settings', () => {
277277
expect(paginator.resourceStrings.igx_paginator_label).toEqual('Per page');
278278
});
279279

280+
it('should have correct accessibility attributes', () => {
281+
const fix = TestBed.createComponent(DefaultPaginatorComponent);
282+
fix.detectChanges();
283+
const paginator = fix.componentInstance.paginator;
284+
const dom = fix.nativeElement;
285+
286+
const label = dom.querySelector('.igx-page-size__label');
287+
const select = dom.querySelector('igx-select');
288+
const input = select.querySelector('input[role="combobox"]');
289+
290+
expect(label.id).toBeTruthy();
291+
expect(label.id).toContain('igx-paginator-');
292+
expect(input.getAttribute('aria-labelledby')).toBe(label.id);
293+
294+
const buttons = dom.querySelectorAll('igx-page-nav button');
295+
expect(buttons[0].getAttribute('aria-label')).toBe(paginator.resourceStrings.igx_paginator_first_page_button_text);
296+
expect(buttons[1].getAttribute('aria-label')).toBe(paginator.resourceStrings.igx_paginator_previous_page_button_text);
297+
expect(buttons[2].getAttribute('aria-label')).toBe(paginator.resourceStrings.igx_paginator_next_page_button_text);
298+
expect(buttons[3].getAttribute('aria-label')).toBe(paginator.resourceStrings.igx_paginator_last_page_button_text);
299+
});
280300
});
281301
@Component({
282302
template: `

projects/igniteui-angular/paginator/src/paginator/paginator.component.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,7 @@ export class IgxPaginatorComponent implements IgxPaginatorToken {
362362
}
363363
}
364364

365+
let NEXT_ID = 0;
365366

366367
@Component({
367368
selector: 'igx-page-size',
@@ -377,6 +378,14 @@ export class IgxPageSizeSelectorComponent {
377378
*/
378379
@HostBinding('class.igx-page-size')
379380
public cssClass = 'igx-page-size';
381+
382+
@HostBinding('attr.id')
383+
@Input()
384+
public id = `igx-paginator-${NEXT_ID++}`;
385+
386+
public get labelId() {
387+
return `${this.id}-label`;
388+
}
380389
}
381390

382391

projects/igniteui-angular/select/src/select/select.component.html

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
[value]="this.selectionValue"
1414
role="combobox"
1515
aria-haspopup="listbox"
16-
[attr.aria-labelledby]="this.label?.id"
16+
[attr.aria-labelledby]="labelledBy || label?.id"
1717
[attr.aria-expanded]="!this.collapsed"
1818
[attr.aria-owns]="this.listId"
1919
[attr.aria-activedescendant]="!this.collapsed ? this.focusedItem?.id : null"
@@ -50,7 +50,7 @@
5050

5151
<!-- #7436 LMB scrolling closes items container - unselectable attribute is IE specific -->
5252
<div #scrollContainer class="igx-drop-down__list-scroll" unselectable="on" [style.maxHeight]="maxHeight"
53-
[attr.id]="this.listId" role="listbox" [attr.aria-labelledby]="this.label?.id">
53+
[attr.id]="this.listId" role="listbox" [attr.aria-labelledby]="labelledBy || label?.id">
5454
<ng-content select="igx-select-item, igx-select-item-group"></ng-content>
5555
</div>
5656

src/app/pagination/pagination.template.html

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,16 +20,16 @@
2020
<igx-paginator-content>
2121
<igx-page-size></igx-page-size>
2222
<span style="margin: 0 20px 0 20px;">{{ (pag.page * pag.perPage) + 1}}-{{(pag.page * pag.perPage) + pag.perPage}} of {{ pag.totalRecords}}</span>
23-
<button [disabled]="pag.isFirstPage" (click)="pag.paginate(0)" igxIconButton="flat">
23+
<button [disabled]="pag.isFirstPage" (click)="pag.paginate(0)" igxIconButton="flat" [attr.aria-label]="pag.resourceStrings.igx_paginator_first_page_button_text">
2424
<igx-icon>first_page</igx-icon>
2525
</button>
26-
<button [disabled]="pag.isFirstPage" (click)="pag.previousPage()" igxIconButton="flat">
26+
<button [disabled]="pag.isFirstPage" (click)="pag.previousPage()" igxIconButton="flat" [attr.aria-label]="pag.resourceStrings.igx_paginator_previous_page_button_text">
2727
<igx-icon>chevron_left</igx-icon>
2828
</button>
29-
<button [disabled]="pag.isLastPage" (click)="pag.nextPage()" igxIconButton="flat">
29+
<button [disabled]="pag.isLastPage" (click)="pag.nextPage()" igxIconButton="flat" [attr.aria-label]="pag.resourceStrings.igx_paginator_next_page_button_text">
3030
<igx-icon>chevron_right</igx-icon>
3131
</button>
32-
<button [disabled]="paginator.isLastPage" (click)="paginator.paginate(paginator.totalPages - 1)" igxIconButton="flat">
32+
<button [disabled]="pag.isLastPage" (click)="pag.paginate(pag.totalPages - 1)" igxIconButton="flat" [attr.aria-label]="pag.resourceStrings.igx_paginator_last_page_button_text">
3333
<igx-icon>last_page</igx-icon>
3434
</button>
3535
</igx-paginator-content>

0 commit comments

Comments
 (0)