license import { Directionality } from '@angular/cdk/bidi' ; import { Overlay , OverlayConfig , OverlayContainer , OverlayRef , ScrollStrategy , } from '@angular/cdk/overlay' ; import { ComponentPortal , ComponentType , PortalInjector , TemplatePortal } from '@angular/cdk/portal' ; import { Location } from '@angular/common' ; import { Inject , Injectable , InjectionToken , Injector , OnDestroy , Optional , SkipSelf , TemplateRef , } from '@angular/core' ; import { defer , Observable , of as observableOf , Subject } from 'rxjs' ; import { startWith } from 'rxjs/operators' ; import { MatDialogConfig } from './dialog-config' ; import { MatDialogContainer } from './dialog-container' ; import { MatDialogRef } from './dialog-ref' ; /** Injection token that can be used to access the data that was passed in to a dialog. */ export const MAT_DIALOG_DATA = new InjectionToken < any > ( 'MatDialogData' ) ; /** Injection token that can be used to specify default dialog options. */ export const MAT_DIALOG_DEFAULT_OPTIONS = new InjectionToken < MatDialogConfig > ( 'mat-dialog-default-options' ) ; /** Injection token that determines the scroll handling while the dialog is open. */ export const MAT_DIALOG_SCROLL_STRATEGY = new InjectionToken < ( ) => ScrollStrategy > ( 'mat-dialog-scroll-strategy' ) ; docs-private export function MAT_DIALOG_SCROLL_STRATEGY_FACTORY ( overlay ) { return ( ) => overlay . scrollStrategies . block ( ) ; } docs-private export function MAT_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY ( overlay ) { return ( ) => overlay . scrollStrategies . block ( ) ; } docs-private export const MAT_DIALOG_SCROLL_STRATEGY_PROVIDER = { provide : MAT_DIALOG_SCROLL_STRATEGY , deps : [ Overlay ] , useFactory : MAT_DIALOG_SCROLL_STRATEGY_PROVIDER_FACTORY , } ; /**
 * Service to open Material Design modal dialogs.
 */ @ Injectable ( ) export class MatDialog implements OnDestroy { private _openDialogsAtThisLevel : MatDialogRef < any > [ ] = [ ] ; private readonly _afterAllClosedAtThisLevel = new Subject < void > ( ) ; private readonly _afterOpenedAtThisLevel = new Subject < MatDialogRef < any > > ( ) ; private _ariaHiddenElements = new Map < Element , string | null > ( ) ; private _scrollStrategy : ( ) => ScrollStrategy ; /** Keeps track of the currently-open dialogs. */ get openDialogs ( ) : MatDialogRef < any > [ ] { return this . _parentDialog ? this . _parentDialog . openDialogs : this . _openDialogsAtThisLevel ; } /** Stream that emits when a dialog has been opened. */ get afterOpened ( ) : Subject < MatDialogRef < any > > { return this . _parentDialog ? this . _parentDialog . afterOpened : this . _afterOpenedAtThisLevel ; } deprecated breaking-change get afterOpen ( ) : Subject < MatDialogRef < any > > { return this . afterOpened ; } get _afterAllClosed ( ) : Subject < void > { const parent = this . _parentDialog ; return parent ? parent . _afterAllClosed : this . _afterAllClosedAtThisLevel ; } /**
     * Stream that emits when all open dialog have finished closing.
     * Will emit on subscribe if there are no open dialogs to begin with.
     */ readonly afterAllClosed : Observable < void > = defer < void > ( ( ) => this . openDialogs . length ? this . _afterAllClosed : this . _afterAllClosed . pipe ( startWith ( undefined ) ) ) ; constructor ( private _overlay , private _injector , @ Optional ( ) private _location , @ Optional ( ) @ Inject ( MAT_DIALOG_DEFAULT_OPTIONS ) private _defaultOptions , @ Inject ( MAT_DIALOG_SCROLL_STRATEGY ) scrollStrategy , @ Optional ( ) @ SkipSelf ( ) private _parentDialog , private _overlayContainer ) { this . _scrollStrategy = scrollStrategy ; } param componentOrTemplateRef param config returns open < T , D = any , R = any > ( componentOrTemplateRef , config ? ) { config = _applyConfigDefaults ( config , this . _defaultOptions || new MatDialogConfig ( ) ) ; if ( config . id && this . getDialogById ( config . id ) ) { throw Error ( `Dialog with id "${ config . id }" exists already. The dialog id must be unique.` ) ; } const overlayRef = this . _createOverlay ( config ) ; const dialogContainer = this . _attachDialogContainer ( overlayRef , config ) ; const dialogRef = this . _attachDialogContent < T , R > ( componentOrTemplateRef , dialogContainer , overlayRef , config ) ; if ( ! this . openDialogs . length ) { this . _hideNonDialogContentFromAssistiveTechnology ( ) ; } this . openDialogs . push ( dialogRef ) ; dialogRef . afterClosed ( ) . subscribe ( ( ) => this . _removeOpenDialog ( dialogRef ) ) ; this . afterOpened . next ( dialogRef ) ; return dialogRef ; } /**
     * Closes all of the currently-open dialogs.
     */ closeAll ( ) { this . _closeDialogs ( this . openDialogs ) ; } param id getDialogById ( id ) { return this . openDialogs . find ( dialog => dialog . id === id ) ; } ngOnDestroy ( ) { this . _closeDialogs ( this . _openDialogsAtThisLevel ) ; this . _afterAllClosedAtThisLevel . complete ( ) ; this . _afterOpenedAtThisLevel . complete ( ) ; } param config returns private _createOverlay ( config ) { const overlayConfig = this . _getOverlayConfig ( config ) ; return this . _overlay . create ( overlayConfig ) ; } param dialogConfig returns private _getOverlayConfig ( dialogConfig ) { const state = new OverlayConfig ( { positionStrategy : this . _overlay . position ( ) . global ( ) , scrollStrategy : dialogConfig . scrollStrategy || this . _scrollStrategy ( ) , panelClass : dialogConfig . panelClass , hasBackdrop : dialogConfig . hasBackdrop , direction : dialogConfig . direction , minWidth : dialogConfig . minWidth , minHeight : dialogConfig . minHeight , maxWidth : dialogConfig . maxWidth , maxHeight : dialogConfig . maxHeight , disposeOnNavigation : dialogConfig . closeOnNavigation } ) ; if ( dialogConfig . backdropClass ) { state . backdropClass = dialogConfig . backdropClass ; } return state ; } param overlay param config returns private _attachDialogContainer ( overlay , config ) { const userInjector = config && config . viewContainerRef && config . viewContainerRef . injector ; const injector = new PortalInjector ( userInjector || this . _injector , new WeakMap ( [ [ MatDialogConfig , config ] ] ) ) ; const containerPortal = new ComponentPortal ( MatDialogContainer , config . viewContainerRef , injector ) ; const containerRef = overlay . attach < MatDialogContainer > ( containerPortal ) ; return containerRef . instance ; } param componentOrTemplateRef param dialogContainer param overlayRef param config returns private _attachDialogContent < T , R > ( componentOrTemplateRef , dialogContainer , overlayRef , config ) { const dialogRef = new MatDialogRef < T , R > ( overlayRef , dialogContainer , this . _location , config . id ) ; if ( config . hasBackdrop ) { overlayRef . backdropClick ( ) . subscribe ( ( ) => { if ( ! dialogRef . disableClose ) { dialogRef . close ( ) ; } } ) ; } if ( componentOrTemplateRef instanceof TemplateRef ) { dialogContainer . attachTemplatePortal ( new TemplatePortal < T > ( componentOrTemplateRef , null ! , < any > { $implicit : config . data , dialogRef } ) ) ; } else { const injector = this . _createInjector < T > ( config , dialogRef , dialogContainer ) ; const contentRef = dialogContainer . attachComponentPortal < T > ( new ComponentPortal ( componentOrTemplateRef , undefined , injector ) ) ; dialogRef . componentInstance = contentRef . instance ; } dialogRef . updateSize ( config . width , config . height ) . updatePosition ( config . position ) ; return dialogRef ; } param config param dialogRef param container returns private _createInjector < T > ( config , dialogRef , dialogContainer ) { const userInjector = config && config . viewContainerRef && config . viewContainerRef . injector ; const injectionTokens = new WeakMap < any , any > ( [ [ MatDialogContainer , dialogContainer ] , [ MAT_DIALOG_DATA , config . data ] , [ MatDialogRef , dialogRef ] ] ) ; if ( config . direction && ( ! userInjector || ! userInjector . get < Directionality | null > ( Directionality , null ) ) ) { injectionTokens . set ( Directionality , { value : config . direction , change : observableOf ( ) } ) ; } return new PortalInjector ( userInjector || this . _injector , injectionTokens ) ; } param dialogRef private _removeOpenDialog ( dialogRef ) { const index = this . openDialogs . indexOf ( dialogRef ) ; if ( index > - 1 ) { this . openDialogs . splice ( index , 1 ) ; if ( ! this . openDialogs . length ) { this . _ariaHiddenElements . forEach ( ( previousValue , element ) => { if ( previousValue ) { element . setAttribute ( 'aria-hidden' , previousValue ) ; } else { element . removeAttribute ( 'aria-hidden' ) ; } } ) ; this . _ariaHiddenElements . clear ( ) ; this . _afterAllClosed . next ( ) ; } } } /**
     * Hides all of the content that isn't an overlay from assistive technology.
     */ private _hideNonDialogContentFromAssistiveTechnology ( ) { const overlayContainer = this . _overlayContainer . getContainerElement ( ) ; if ( overlayContainer . parentElement ) { const siblings = overlayContainer . parentElement . children ; for ( let i = siblings . length - 1 ; i > - 1 ; i -- ) { let sibling = siblings [ i ] ; if ( sibling !== overlayContainer && sibling . nodeName !== 'SCRIPT' && sibling . nodeName !== 'STYLE' && ! sibling . hasAttribute ( 'aria-live' ) ) { this . _ariaHiddenElements . set ( sibling , sibling . getAttribute ( 'aria-hidden' ) ) ; sibling . setAttribute ( 'aria-hidden' , 'true' ) ; } } } } /** Closes all of the dialogs in an array. */ private _closeDialogs ( dialogs ) { let i = dialogs . length ; while ( i -- ) { dialogs [ i ] . close ( ) ; } } } param config param defaultOptions returns function _applyConfigDefaults ( config ? , defaultOptions ? ) { return { ... defaultOptions , ... config } ; }