Issue
I am attempting to force a screen reader in Ionic 5 to focus on and announce an element.
My template element:
<ion-title tabindex="-1" #title id="title" role="heading" aria-level="1" class="title">My Title</ion-title>
I have attempted to access the element via document and as a Viewchild:
@ViewChild('title', { read: ElementRef }) title: ElementRef;
const title: any = document.getElementById('title');
I attempt to focus after a delay with this test:
ionViewWillEnter(): void {
setTimeout(() => {
const title: any = document.getElementById('title');
if (title) {
title.focus();
}
}, 3000);
setTimeout(() => {
this.title.nativeElement.focus();
}, 5000);
}
Neither of these focus, however. The screen reader does not announce the title in either Android nor iOS.
Update
Just to clarify, I need the screen reader position to move to a specified element. Focusing on an element as described will not move the screen reader position.
Any help would be appreciated, here's my Ionic info:
Ionic CLI : 5.4.16
Ionic Framework : @ionic/angular 5.5.3
@angular-devkit/build-angular : 0.901.15
@angular-devkit/schematics : 9.1.15
@angular/cli : 9.1.15
@ionic/angular-toolkit : 2.3.3
Capacitor:
Capacitor CLI : 2.4.2
@capacitor/core : 2.4.0
Solution
I created a BasePage for all the Ionic pages to extend. It captures the active element on click and focus events and focuses on that element when the page enters again.
It also automatically attempts to find the ion-title and focus on that if there is no previously active element to focus.
This should cover the basic needs. You can tweak add timeouts to the focus method
import { Component, ElementRef, HostListener } from '@angular/core';
import { ViewDidEnter } from '@ionic/angular';
import { isNullOrUndefined } from 'util';
@Component({
template: ''
})
export class BasePage implements ViewDidEnter {
private _previouslyActiveElement: HTMLElement;
constructor(protected elementRef: ElementRef) {}
ionViewDidEnter() {
if (!isNullOrUndefined(this._previouslyActiveElement)) {
this.focusOnElement(this._previouslyActiveElement);
} else {
if (
!isNullOrUndefined(this.elementRef.nativeElement) &&
this.elementRef.nativeElement.querySelectorAll('[autofocus]').length === 0) {
const initialFocusElement: HTMLElement = <HTMLElement>this.elementRef.nativeElement.getElementsByTagName('ion-title')[0];
if (!isNullOrUndefined(initialFocusElement)) {
this.focusOnElement(initialFocusElement);
}
}
}
}
@HostListener('focusin', ['$event.target'])
@HostListener('click', ['$event.target'])
capturePreviouslyActiveElement(element: HTMLElement) {
this._previouslyActiveElement = element;
}
focusOnElement(element: HTMLElement): void {
if (isNullOrUndefined(element)) {
return;
}
try {
// Make sure it's focusable
if (isNullOrUndefined(element.getAttribute('tabindex'))) {
element.setAttribute('tabindex', '-1');
}
element.focus();
} catch (err) {
console.log('error handling aria focus ' + err);
}
}
}
Answered By - codeetcetera
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.