9
9
import { LiveAnnouncer } from '@angular/cdk/a11y' ;
10
10
import { BreakpointObserver , Breakpoints } from '@angular/cdk/layout' ;
11
11
import { Overlay , OverlayConfig , OverlayRef } from '@angular/cdk/overlay' ;
12
- import { ComponentPortal , ComponentType , PortalInjector } from '@angular/cdk/portal' ;
12
+ import { ComponentPortal , TemplatePortal , ComponentType , PortalInjector } from '@angular/cdk/portal' ;
13
13
import {
14
14
ComponentRef ,
15
+ EmbeddedViewRef ,
15
16
Inject ,
16
17
Injectable ,
17
18
Injector ,
18
19
InjectionToken ,
19
20
Optional ,
20
21
SkipSelf ,
22
+ TemplateRef ,
21
23
} from '@angular/core' ;
22
24
import { take } from 'rxjs/operators/take' ;
23
25
import { takeUntil } from 'rxjs/operators/takeUntil' ;
@@ -72,41 +74,21 @@ export class MatSnackBar {
72
74
* @param component Component to be instantiated.
73
75
* @param config Extra configuration for the snack bar.
74
76
*/
75
- openFromComponent < T > ( component : ComponentType < T > , config ?: MatSnackBarConfig ) : MatSnackBarRef < T > {
76
- const _config = { ...this . _defaultConfig , ...config } ;
77
- const snackBarRef = this . _attach ( component , _config ) ;
78
-
79
- // When the snackbar is dismissed, clear the reference to it.
80
- snackBarRef . afterDismissed ( ) . subscribe ( ( ) => {
81
- // Clear the snackbar ref if it hasn't already been replaced by a newer snackbar.
82
- if ( this . _openedSnackBarRef == snackBarRef ) {
83
- this . _openedSnackBarRef = null ;
84
- }
85
- } ) ;
86
-
87
- if ( this . _openedSnackBarRef ) {
88
- // If a snack bar is already in view, dismiss it and enter the
89
- // new snack bar after exit animation is complete.
90
- this . _openedSnackBarRef . afterDismissed ( ) . subscribe ( ( ) => {
91
- snackBarRef . containerInstance . enter ( ) ;
92
- } ) ;
93
- this . _openedSnackBarRef . dismiss ( ) ;
94
- } else {
95
- // If no snack bar is in view, enter the new snack bar.
96
- snackBarRef . containerInstance . enter ( ) ;
97
- }
98
-
99
- // If a dismiss timeout is provided, set up dismiss based on after the snackbar is opened.
100
- if ( _config . duration && _config . duration > 0 ) {
101
- snackBarRef . afterOpened ( ) . subscribe ( ( ) => snackBarRef . _dismissAfter ( _config ! . duration ! ) ) ;
102
- }
103
-
104
- if ( _config . announcementMessage ) {
105
- this . _live . announce ( _config . announcementMessage , _config . politeness ) ;
106
- }
77
+ openFromComponent < T > ( component : ComponentType < T > , config ?: MatSnackBarConfig ) :
78
+ MatSnackBarRef < T > {
79
+ return this . _attach ( component , config ) as MatSnackBarRef < T > ;
80
+ }
107
81
108
- this . _openedSnackBarRef = snackBarRef ;
109
- return this . _openedSnackBarRef ;
82
+ /**
83
+ * Creates and dispatches a snack bar with a custom template for the content, removing any
84
+ * currently opened snack bars.
85
+ *
86
+ * @param template Template to be instantiated.
87
+ * @param config Extra configuration for the snack bar.
88
+ */
89
+ openFromTemplate ( template : TemplateRef < any > , config ?: MatSnackBarConfig ) :
90
+ MatSnackBarRef < EmbeddedViewRef < any > > {
91
+ return this . _attach ( template , config ) ;
110
92
}
111
93
112
94
/**
@@ -148,18 +130,31 @@ export class MatSnackBar {
148
130
}
149
131
150
132
/**
151
- * Places a new component as the content of the snack bar container.
133
+ * Places a new component or a template as the content of the snack bar container.
152
134
*/
153
- private _attach < T > ( component : ComponentType < T > , config : MatSnackBarConfig ) : MatSnackBarRef < T > {
135
+ private _attach < T > ( content : ComponentType < T > | TemplateRef < T > , userConfig ?: MatSnackBarConfig ) :
136
+ MatSnackBarRef < T | EmbeddedViewRef < any > > {
137
+
138
+ const config = { ...this . _defaultConfig , ...userConfig } ;
154
139
const overlayRef = this . _createOverlay ( config ) ;
155
140
const container = this . _attachSnackBarContainer ( overlayRef , config ) ;
156
- const snackBarRef = new MatSnackBarRef < T > ( container , overlayRef ) ;
157
- const injector = this . _createInjector ( config , snackBarRef ) ;
158
- const portal = new ComponentPortal ( component , undefined , injector ) ;
159
- const contentRef = container . attachComponentPortal ( portal ) ;
141
+ const snackBarRef = new MatSnackBarRef < T | EmbeddedViewRef < any > > ( container , overlayRef ) ;
142
+
143
+ if ( content instanceof TemplateRef ) {
144
+ const portal = new TemplatePortal ( content , null ! , {
145
+ $implicit : config . data ,
146
+ snackBarRef
147
+ } as any ) ;
160
148
161
- // We can't pass this via the injector, because the injector is created earlier.
162
- snackBarRef . instance = contentRef . instance ;
149
+ snackBarRef . instance = container . attachTemplatePortal ( portal ) ;
150
+ } else {
151
+ const injector = this . _createInjector ( config , snackBarRef ) ;
152
+ const portal = new ComponentPortal ( content , undefined , injector ) ;
153
+ const contentRef = container . attachComponentPortal < T > ( portal ) ;
154
+
155
+ // We can't pass this via the injector, because the injector is created earlier.
156
+ snackBarRef . instance = contentRef . instance ;
157
+ }
163
158
164
159
// Subscribe to the breakpoint observer and attach the mat-snack-bar-handset class as
165
160
// appropriate. This class is applied to the overlay element because the overlay must expand to
@@ -174,7 +169,41 @@ export class MatSnackBar {
174
169
}
175
170
} ) ;
176
171
177
- return snackBarRef ;
172
+ this . _animateSnackBar ( snackBarRef , config ) ;
173
+ this . _openedSnackBarRef = snackBarRef ;
174
+ return this . _openedSnackBarRef ;
175
+ }
176
+
177
+ /** Animates the old snack bar out and the new one in. */
178
+ private _animateSnackBar ( snackBarRef : MatSnackBarRef < any > , config : MatSnackBarConfig ) {
179
+ // When the snackbar is dismissed, clear the reference to it.
180
+ snackBarRef . afterDismissed ( ) . subscribe ( ( ) => {
181
+ // Clear the snackbar ref if it hasn't already been replaced by a newer snackbar.
182
+ if ( this . _openedSnackBarRef == snackBarRef ) {
183
+ this . _openedSnackBarRef = null ;
184
+ }
185
+ } ) ;
186
+
187
+ if ( this . _openedSnackBarRef ) {
188
+ // If a snack bar is already in view, dismiss it and enter the
189
+ // new snack bar after exit animation is complete.
190
+ this . _openedSnackBarRef . afterDismissed ( ) . subscribe ( ( ) => {
191
+ snackBarRef . containerInstance . enter ( ) ;
192
+ } ) ;
193
+ this . _openedSnackBarRef . dismiss ( ) ;
194
+ } else {
195
+ // If no snack bar is in view, enter the new snack bar.
196
+ snackBarRef . containerInstance . enter ( ) ;
197
+ }
198
+
199
+ // If a dismiss timeout is provided, set up dismiss based on after the snackbar is opened.
200
+ if ( config . duration && config . duration > 0 ) {
201
+ snackBarRef . afterOpened ( ) . subscribe ( ( ) => snackBarRef . _dismissAfter ( config . duration ! ) ) ;
202
+ }
203
+
204
+ if ( config . announcementMessage ) {
205
+ this . _live . announce ( config . announcementMessage , config . politeness ) ;
206
+ }
178
207
}
179
208
180
209
/**
0 commit comments