如何使PrimeNG下拉键盘可访问

时间:2017-09-14 07:28:19

标签: accessibility angular2-forms dropdown primeng

我想让下拉键盘可访问。现在,当我使用键盘向上和向下箭头时它不起作用。我应用了tabindex但仍然没有工作。任何人都对此有所了解..

<p-dropdown [options]="cities" tabindex="1" placeholder="Select an option"></p-dropdown

2 个答案:

答案 0 :(得分:1)

我尝试使用键盘向上和向下箭头正常工作:

npm版本:

"primeng": "^4.1.3"

在html文件中

<p-dropdown [options]="cities" [(ngModel)]="selectedCity" tabindex="1" placeholder="Select an option"></p-dropdown>

module.ts

import { DropdownModule } from 'primeng/primeng';

@NgModule({
    imports: [
         DropdownModule
    ]
})

<强> component.ts

import {SelectItem} from 'primeng/primeng';

    cities: SelectItem[];
    selectedCity: string;

答案 1 :(得分:0)

PrimeNG默认不支持阅读下拉选项。默认行为是通过箭头导航并更改值。制表符的默认键操作是隐藏元素项的叠加层。我的解决方案强制制表符选择下拉选项,然后按Enter键更改值。

我准备了angular指令,该指令可以覆盖默认的下拉菜单行为。您可以添加add指令do模块并将其导入到您要使用此更改的位置。

PrimeNG 8.0.0测试:

@Directive({
    selector: 'p-dropdown',
})
export class DropdownDirective implements OnInit, OnDestroy {
    readonly KEY_DOWN_EVENT: string = 'keydown';
    readonly FOCUS_IN_EVENT: string = 'focusin';
    readonly TABINDEX_ATTRIBUTE: string = 'tabindex';
    readonly LIST_ITEM_SELECTOR: string = 'li';

    private focusInSubscription: Subscription = new Subscription();
    private subscriptions: Subscription = new Subscription();
    private listElementSubscriptions: Subscription[] = [];
    private readonly dropdownHtmlElement: HTMLElement;

    constructor(private dropdown: Dropdown,
                private elementRef: ElementRef) {
        this.dropdownHtmlElement = this.elementRef.nativeElement as HTMLElement;
    }

    ngOnInit(): void {
        this.replaceKeyDownAction();
        this.subscribeToDropdownShowEvent();
        this.subscribeToDropdownHideEvent();
    }

    ngOnDestroy(): void {
        this.subscriptions.unsubscribe();
    }

    private subscribeToDropdownShowEvent() {
        this.subscriptions.add(
            this.dropdown.onShow.subscribe(() => {
                this.updateElementsList();
                this.subscribeToFocusInEvent();
            }),
        );
    }

    private subscribeToDropdownHideEvent() {
        this.subscriptions.add(
            this.dropdown.onHide.subscribe(() => {
                this.unsubscribeFromFocusInEvent();
                this.unsubscribeFromListElementsKeyDownEvents();
            }),
        );
    }

    private updateElementsList() {
        const listElements = this.dropdownHtmlElement.querySelectorAll<HTMLLIElement>(this.LIST_ITEM_SELECTOR);

        listElements.forEach((listElement: HTMLLIElement) => {
            this.subscribeToListElementKeyDownEvent(listElement);
            listElement.setAttribute(this.TABINDEX_ATTRIBUTE, '0');
        });
    }

    private subscribeToListElementKeyDownEvent(listElement: HTMLLIElement) {
        this.listElementSubscriptions.push(
            fromEvent(listElement, this.KEY_DOWN_EVENT)
                .pipe(filter((event: KeyboardEvent) => event.key === KEYBOARD_KEY.ENTER))
                .subscribe(() => {
                    // Simulation of mouse click of list element (trigger with (click) event in p-dropdownItem component which is child element of p-dropdown)
                    listElement.click();
                }),
        );
    }

    private unsubscribeFromListElementsKeyDownEvents() {
        this.listElementSubscriptions.forEach((singleSubscription: Subscription) => singleSubscription.unsubscribe());
        this.listElementSubscriptions = [];
    }

    private subscribeToFocusInEvent() {
        this.focusInSubscription = fromEvent(document, this.FOCUS_IN_EVENT).subscribe(({target}) => {

            // Situation when focus element is outside dropdown component
            if (!this.dropdownHtmlElement.contains(target as HTMLElement)) {
                this.dropdown.hide();
            }
        });
    }

    private unsubscribeFromFocusInEvent() {
        this.focusInSubscription.unsubscribe();
    }

    /**
     * Overwrite default onKeydown method from PrimeNG dropdown component
     */
    private replaceKeyDownAction() {
        const onKeyDownOriginFn = this.dropdown.onKeydown.bind(this.dropdown);

        this.dropdown.onKeydown = (event: KeyboardEvent, search: boolean) => {
            if (event.which === 9) {
                // Napisuję domyślne zachowanie tabulatora zdefiniowanego w klasie komponentu Dropdown z biblioteki PrimeNG
            } else {
                onKeyDownOriginFn(event, search);
            }
        }
    }
}