@@ -18,17 +18,21 @@ import {
1818 inject ,
1919 DOCUMENT ,
2020} from '@angular/core' ;
21+ import { DomSanitizer , SafeHtml } from '@angular/platform-browser' ;
2122import { Subscription } from 'rxjs' ;
2223import {
2324 AriaLivePoliteness ,
2425 LiveAnnouncerDefaultOptions ,
2526 LIVE_ANNOUNCER_ELEMENT_TOKEN ,
2627 LIVE_ANNOUNCER_DEFAULT_OPTIONS ,
2728} from './live-announcer-tokens' ;
28- import { _CdkPrivateStyleLoader , _VisuallyHiddenLoader } from '../../private' ;
29+ import { _CdkPrivateStyleLoader , _VisuallyHiddenLoader , _setInnerHtml } from '../../private' ;
2930
3031let uniqueIds = 0 ;
3132
33+ /** Possible types for a message that can be announced by the `LiveAnnouncer`. */
34+ export type LiveAnnouncerMessage = string | SafeHtml ;
35+
3236@Injectable ( { providedIn : 'root' } )
3337export class LiveAnnouncer implements OnDestroy {
3438 private _ngZone = inject ( NgZone ) ;
@@ -38,6 +42,7 @@ export class LiveAnnouncer implements OnDestroy {
3842
3943 private _liveElement : HTMLElement ;
4044 private _document = inject ( DOCUMENT ) ;
45+ private _sanitizer = inject ( DomSanitizer ) ;
4146 private _previousTimeout : ReturnType < typeof setTimeout > ;
4247 private _currentPromise : Promise < void > | undefined ;
4348 private _currentResolve : ( ( ) => void ) | undefined ;
@@ -54,15 +59,15 @@ export class LiveAnnouncer implements OnDestroy {
5459 * @param message Message to be announced to the screen reader.
5560 * @returns Promise that will be resolved when the message is added to the DOM.
5661 */
57- announce ( message : string ) : Promise < void > ;
62+ announce ( message : LiveAnnouncerMessage ) : Promise < void > ;
5863
5964 /**
6065 * Announces a message to screen readers.
6166 * @param message Message to be announced to the screen reader.
6267 * @param politeness The politeness of the announcer element.
6368 * @returns Promise that will be resolved when the message is added to the DOM.
6469 */
65- announce ( message : string , politeness ?: AriaLivePoliteness ) : Promise < void > ;
70+ announce ( message : LiveAnnouncerMessage , politeness ?: AriaLivePoliteness ) : Promise < void > ;
6671
6772 /**
6873 * Announces a message to screen readers.
@@ -72,7 +77,7 @@ export class LiveAnnouncer implements OnDestroy {
7277 * 100ms after `announce` has been called.
7378 * @returns Promise that will be resolved when the message is added to the DOM.
7479 */
75- announce ( message : string , duration ?: number ) : Promise < void > ;
80+ announce ( message : LiveAnnouncerMessage , duration ?: number ) : Promise < void > ;
7681
7782 /**
7883 * Announces a message to screen readers.
@@ -83,9 +88,13 @@ export class LiveAnnouncer implements OnDestroy {
8388 * 100ms after `announce` has been called.
8489 * @returns Promise that will be resolved when the message is added to the DOM.
8590 */
86- announce ( message : string , politeness ?: AriaLivePoliteness , duration ?: number ) : Promise < void > ;
91+ announce (
92+ message : LiveAnnouncerMessage ,
93+ politeness ?: AriaLivePoliteness ,
94+ duration ?: number ,
95+ ) : Promise < void > ;
8796
88- announce ( message : string , ...args : any [ ] ) : Promise < void > {
97+ announce ( message : LiveAnnouncerMessage , ...args : any [ ] ) : Promise < void > {
8998 const defaultOptions = this . _defaultOptions ;
9099 let politeness : AriaLivePoliteness | undefined ;
91100 let duration : number | undefined ;
@@ -127,7 +136,11 @@ export class LiveAnnouncer implements OnDestroy {
127136
128137 clearTimeout ( this . _previousTimeout ) ;
129138 this . _previousTimeout = setTimeout ( ( ) => {
130- this . _liveElement . textContent = message ;
139+ if ( ! message || typeof message === 'string' ) {
140+ this . _liveElement . textContent = message ;
141+ } else {
142+ _setInnerHtml ( this . _liveElement , message , this . _sanitizer ) ;
143+ }
131144
132145 if ( typeof duration === 'number' ) {
133146 this . _previousTimeout = setTimeout ( ( ) => this . clear ( ) , duration ) ;
0 commit comments