diff --git a/src/core/features/editor/components/rich-text-editor/core-editor-rich-text-editor.html b/src/core/features/editor/components/rich-text-editor/core-editor-rich-text-editor.html index e3422805d..37f354022 100644 --- a/src/core/features/editor/components/rich-text-editor/core-editor-rich-text-editor.html +++ b/src/core/features/editor/components/rich-text-editor/core-editor-rich-text-editor.html @@ -5,6 +5,7 @@ class="core-rte-editor" role="textbox" contenteditable="true" + [attr.aria-labelledby]="ariaLabelledBy" [attr.data-placeholder-text]="placeholder" (focus)="showToolbar($event)" (blur)="hideToolbar($event)" diff --git a/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts b/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts index 0b53152f3..59e23bbad 100644 --- a/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts +++ b/src/core/features/editor/components/rich-text-editor/rich-text-editor.ts @@ -23,6 +23,7 @@ import { AfterContentInit, OnDestroy, Optional, + AfterViewInit, } from '@angular/core'; import { FormControl } from '@angular/forms'; import { IonTextarea, IonContent, IonSlides } from '@ionic/angular'; @@ -51,7 +52,7 @@ import { CoreEditorOffline } from '../../services/editor-offline'; templateUrl: 'core-editor-rich-text-editor.html', styleUrls: ['rich-text-editor.scss'], }) -export class CoreEditorRichTextEditorComponent implements OnInit, AfterContentInit, OnDestroy { +export class CoreEditorRichTextEditorComponent implements OnInit, AfterContentInit, AfterViewInit, OnDestroy { // Based on: https://github.com/judgewest2000/Ionic3RichText/ // @todo: Anchor button, fullscreen... @@ -87,6 +88,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterContentIn protected valueChangeSubscription?: Subscription; protected keyboardObserver?: CoreEventObserver; protected resetObserver?: CoreEventObserver; + protected labelObserver?: MutationObserver; protected initHeightInterval?: number; protected isCurrentView = true; protected toolbarButtonWidth = 44; @@ -109,6 +111,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterContentIn toolbarPrevHidden = true; toolbarNextHidden = false; canScanQR = false; + ariaLabelledBy?: string; infoMessage?: string; direction = 'ltr'; toolbarStyles = { @@ -209,6 +212,20 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterContentIn } } + /** + * @inheritdoc + */ + async ngAfterViewInit(): Promise { + const label = this.element.closest('ion-item')?.querySelector('ion-label'); + + if (!label) { + return; + } + + this.labelObserver = new MutationObserver(() => this.ariaLabelledBy = label.getAttribute('id') ?? undefined); + this.labelObserver.observe(label, { attributes: true, attributeFilter: ['id'] }); + } + /** * Set listeners and observers. */ @@ -1118,6 +1135,7 @@ export class CoreEditorRichTextEditorComponent implements OnInit, AfterContentIn this.resizeObserver?.disconnect(); this.resetObserver?.off(); this.keyboardObserver?.off(); + this.labelObserver?.disconnect(); } }