diff --git a/demos/src/app/app-routing.module.ts b/demos/src/app/app-routing.module.ts index 0565d0993..bf29781d4 100644 --- a/demos/src/app/app-routing.module.ts +++ b/demos/src/app/app-routing.module.ts @@ -67,7 +67,7 @@ const routes: Routes = [ {path: 'slider-demo', loadChildren: () => import('./components/slider/module').then(m => m.SliderModule)}, { path: 'snackbar-demo', loadChildren: () => - import('./components/snackbar-demo/snackbar.module').then(m => m.SnackbarModule) + import('./components/snackbar/module').then(m => m.SnackbarModule) }, {path: 'switch-demo', loadChildren: () => import('./components/switch-demo/switch.module').then(m => m.SwitchModule)}, {path: 'tabs-demo', loadChildren: () => import('./components/tabs-demo/tabs.module').then(m => m.TabsModule)}, diff --git a/demos/src/app/components/snackbar-demo/examples.html b/demos/src/app/components/snackbar-demo/examples.html deleted file mode 100644 index 37868e734..000000000 --- a/demos/src/app/components/snackbar-demo/examples.html +++ /dev/null @@ -1,80 +0,0 @@ -
MdcSnackbarDismissReason
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Custom
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Theme
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Open from Component
+
+
+
+
+
+
\ No newline at end of file
diff --git a/demos/src/app/components/snackbar/module.ts b/demos/src/app/components/snackbar/module.ts
new file mode 100644
index 000000000..12d060416
--- /dev/null
+++ b/demos/src/app/components/snackbar/module.ts
@@ -0,0 +1,20 @@
+import {NgModule} from '@angular/core';
+
+import {SharedModule} from '../../shared.module';
+import {RoutingModule, ROUTE_DECLARATIONS} from './routing.module';
+
+import {
+ BurritosNotification
+} from './snackbar';
+
+@NgModule({
+ imports: [
+ SharedModule,
+ RoutingModule
+ ],
+ declarations: [
+ ROUTE_DECLARATIONS,
+ BurritosNotification,
+ ]
+})
+export class SnackbarModule {}
diff --git a/demos/src/app/components/snackbar/routing.module.ts b/demos/src/app/components/snackbar/routing.module.ts
new file mode 100644
index 000000000..e563f0e12
--- /dev/null
+++ b/demos/src/app/components/snackbar/routing.module.ts
@@ -0,0 +1,29 @@
+import {NgModule} from '@angular/core';
+import {Routes, RouterModule} from '@angular/router';
+
+import {Api, Examples, Sass, Snackbar} from './snackbar';
+
+export const ROUTE_DECLARATIONS = [
+ Api,
+ Examples,
+ Sass,
+ Snackbar
+];
+
+const ROUTES: Routes = [
+ {
+ path: '', component: Snackbar,
+ children: [
+ {path: '', redirectTo: 'api'},
+ {path: 'api', component: Api},
+ {path: 'sass', component: Sass},
+ {path: 'examples', component: Examples}
+ ]
+ }
+];
+
+@NgModule({
+ imports: [RouterModule.forChild(ROUTES)],
+ exports: [RouterModule]
+})
+export class RoutingModule {}
diff --git a/demos/src/app/components/snackbar-demo/sass.html b/demos/src/app/components/snackbar/sass.html
similarity index 100%
rename from demos/src/app/components/snackbar-demo/sass.html
rename to demos/src/app/components/snackbar/sass.html
diff --git a/demos/src/app/components/snackbar-demo/snackbar-demo.ts b/demos/src/app/components/snackbar/snackbar.ts
similarity index 97%
rename from demos/src/app/components/snackbar-demo/snackbar-demo.ts
rename to demos/src/app/components/snackbar/snackbar.ts
index 4757597ff..dd597e20c 100644
--- a/demos/src/app/components/snackbar-demo/snackbar-demo.ts
+++ b/demos/src/app/components/snackbar/snackbar.ts
@@ -11,7 +11,7 @@ interface CustomClasses {
}
@Component({template: ' '})
-export class SnackbarDemo implements OnInit {
+export class Snackbar implements OnInit {
@ViewChild(ComponentViewer, {static: true}) _componentViewer: ComponentViewer;
ngOnInit(): void {
@@ -38,6 +38,9 @@ export class Api {}
@Component({templateUrl: './sass.html'})
export class Sass {}
+@Component({template: 'Burritos are on the way.
'})
+export class BurritosNotification {}
+
@Component({templateUrl: './examples.html'})
export class Examples {
constructor(private snackbar: MdcSnackbar) {}
@@ -116,6 +119,10 @@ export class Examples {
});
}
+ openFromComponent() {
+ this.snackbar.openFromComponent(BurritosNotification);
+ }
+
//
// Examples
//
diff --git a/packages/snackbar/module.ts b/packages/snackbar/module.ts
index 9c81494df..cac25f4d9 100644
--- a/packages/snackbar/module.ts
+++ b/packages/snackbar/module.ts
@@ -4,8 +4,9 @@ import {OverlayModule} from '@angular/cdk/overlay';
import {PortalModule} from '@angular/cdk/portal';
import {MdcButtonModule} from '@angular-mdc/web/button';
-import {MdcSnackbarComponent} from './snackbar.component';
+import {MdcSnackbarBase} from './snackbar-base';
import {MdcSnackbarContainer} from './snackbar-container';
+import {MdcSnackbarComponent} from './snackbar.component';
@NgModule({
imports: [
@@ -15,7 +16,7 @@ import {MdcSnackbarContainer} from './snackbar-container';
MdcButtonModule
],
exports: [MdcSnackbarContainer],
- declarations: [MdcSnackbarContainer, MdcSnackbarComponent],
- entryComponents: [MdcSnackbarContainer, MdcSnackbarComponent]
+ declarations: [MdcSnackbarContainer, MdcSnackbarBase, MdcSnackbarComponent],
+ entryComponents: [MdcSnackbarContainer, MdcSnackbarComponent, MdcSnackbarBase]
})
export class MdcSnackbarModule { }
diff --git a/packages/snackbar/public-api.ts b/packages/snackbar/public-api.ts
index 69c91a42d..aff52c8d4 100644
--- a/packages/snackbar/public-api.ts
+++ b/packages/snackbar/public-api.ts
@@ -2,5 +2,6 @@ export * from './module';
export * from './snackbar-container';
export * from './snackbar-config';
export * from './snackbar-ref';
+export * from './snackbar-base';
export * from './snackbar.component';
export * from './snackbar';
diff --git a/packages/snackbar/snackbar-base.ts b/packages/snackbar/snackbar-base.ts
new file mode 100644
index 000000000..0a3a8f202
--- /dev/null
+++ b/packages/snackbar/snackbar-base.ts
@@ -0,0 +1,143 @@
+import {
+ ChangeDetectionStrategy,
+ ChangeDetectorRef,
+ Component,
+ ElementRef,
+ Inject,
+ OnDestroy,
+ OnInit,
+ ViewChild,
+ ViewEncapsulation
+} from '@angular/core';
+import {LiveAnnouncer} from '@angular/cdk/a11y';
+
+import {MDCComponent} from '@angular-mdc/web/base';
+import {MdcSnackbarRef, MdcSnackbarDismissReason} from './snackbar-ref';
+import {MDC_SNACKBAR_DATA, MdcSnackbarConfig} from './snackbar-config';
+
+import {MDCSnackbarFoundation, MDCSnackbarAdapter} from '@material/snackbar';
+
+@Component({
+ moduleId: module.id,
+ selector: 'mdc-snackbar',
+ host: {
+ 'class': 'mdc-snackbar',
+ '[dir]': 'this.config.direction',
+ '[class.mdc-snackbar--stacked]': 'config.stacked',
+ '[class.mdc-snackbar--leading]': 'config.leading',
+ '[class.ngx-mdc-snackbar--trailing]': 'config.trailing',
+ '(keydown)': '_onKeydown($event)'
+ },
+ template: ` `,
+ changeDetection: ChangeDetectionStrategy.OnPush,
+ encapsulation: ViewEncapsulation.None,
+ providers: [LiveAnnouncer]
+})
+export class MdcSnackbarBase extends MDCComponent implements OnInit, OnDestroy {
+ @ViewChild('label', {static: true}) label!: ElementRef;
+ @ViewChild('action', {static: false}) action?: ElementRef;
+ @ViewChild('dismiss', {static: false}) dismiss?: ElementRef;
+
+ get config(): MdcSnackbarConfig {
+ return this.snackbarRef.componentInstance.snackbarConfig;
+ }
+
+ getDefaultFoundation() {
+ const adapter: MDCSnackbarAdapter = {
+ addClass: (className: string) => this._getHostElement().classList.add(className),
+ removeClass: (className: string) => this._getHostElement().classList.remove(className),
+ announce: () => this.label.nativeElement ? this.liveAnnouncer.announce(this.config.data.message,
+ this.config.politeness, this.config.timeoutMs || MDCSnackbarFoundation.numbers.ARIA_LIVE_DELAY_MS) : {},
+ notifyClosing: () => {},
+ notifyOpened: () => {},
+ notifyOpening: () => {},
+ notifyClosed: (reason: MdcSnackbarDismissReason | string) => this.snackbarRef.dismiss(reason)
+ };
+ return new MDCSnackbarFoundation(adapter);
+ }
+
+ constructor(
+ public changeDetectorRef: ChangeDetectorRef,
+ public liveAnnouncer: LiveAnnouncer,
+ public elementRef: ElementRef,
+ public snackbarRef: MdcSnackbarRef,
+ @Inject(MDC_SNACKBAR_DATA) public data: any) {
+ super(elementRef);
+ }
+
+ ngOnInit(): void {
+ this.changeDetectorRef.detectChanges();
+
+ this._applyClasses();
+ this._applyConfig();
+ }
+
+ ngOnDestroy(): void {
+ this._foundation?.destroy();
+ }
+
+ _onKeydown(evt: KeyboardEvent): void {
+ this._foundation.handleKeyDown(evt);
+ }
+
+ _onActionClick(evt: MouseEvent): void {
+ this._foundation.handleActionButtonClick(evt);
+ }
+
+ _onActionIconClick(evt: MouseEvent): void {
+ this._foundation.handleActionIconClick(evt);
+ }
+
+ open(): void {
+ this._foundation.open();
+ }
+
+ close(reason?: MdcSnackbarDismissReason): void {
+ this._foundation.close(reason !== undefined ? reason.action ? 'action' : reason.dismiss ? 'dismiss' : '' : '');
+ }
+
+ private _applyClasses(): void {
+ const classes = this.config.classes;
+ if (classes) {
+ if (classes instanceof Array) {
+ this._getHostElement().classList.add(...this.config.classes as string[]);
+ } else {
+ this._getHostElement().classList.toggle(classes);
+ }
+ }
+
+ const actionClasses = this.config.actionClasses;
+ if (actionClasses && this.action) {
+ if (actionClasses instanceof Array) {
+ this.action.nativeElement.classList.add(...this.config.actionClasses as string[]);
+ } else {
+ this.action.nativeElement.classList.toggle(actionClasses);
+ }
+ }
+
+ if (this.dismiss) {
+ const dismissClasses = this.config.dismissClasses;
+ if (dismissClasses) {
+ if (dismissClasses instanceof Array) {
+ this.dismiss.nativeElement.classList.add(...this.config.dismissClasses as string[]);
+ } else {
+ this.dismiss.nativeElement.classList.toggle(dismissClasses);
+ }
+ }
+ }
+ }
+
+ private _applyConfig(): void {
+ if (this.config.timeoutMs) {
+ this._foundation.setTimeoutMs(this.config.timeoutMs);
+ }
+ if (this.config.dismiss) {
+ this._foundation.setCloseOnEscape(this.config.closeOnEscape ? true : false);
+ }
+ }
+
+ /** Retrieves the DOM element of the component host. */
+ private _getHostElement(): HTMLElement {
+ return this.elementRef.nativeElement;
+ }
+}
diff --git a/packages/snackbar/snackbar-container.ts b/packages/snackbar/snackbar-container.ts
index 24b897bc5..39c1dbda0 100644
--- a/packages/snackbar/snackbar-container.ts
+++ b/packages/snackbar/snackbar-container.ts
@@ -1,9 +1,3 @@
-import {
- BasePortalOutlet,
- CdkPortalOutlet,
- ComponentPortal,
- TemplatePortal,
-} from '@angular/cdk/portal';
import {
ChangeDetectionStrategy,
Component,
@@ -14,10 +8,17 @@ import {
ViewChild,
ViewEncapsulation,
} from '@angular/core';
+import {
+ BasePortalOutlet,
+ CdkPortalOutlet,
+ ComponentPortal,
+ TemplatePortal,
+} from '@angular/cdk/portal';
import {Subject} from 'rxjs';
import {take} from 'rxjs/operators';
import {MdcSnackbarConfig} from './snackbar-config';
+
@Component({
moduleId: module.id,
selector: 'mdc-snackbar-container',
@@ -35,17 +36,18 @@ export class MdcSnackbarContainer extends BasePortalOutlet implements OnDestroy
constructor(
private _ngZone: NgZone,
public snackbarConfig: MdcSnackbarConfig) {
-
super();
}
/** Attach a component portal as content to this snackbar container. */
attachComponentPortal(portal: ComponentPortal): ComponentRef {
+ this._assertNotAttached();
return this._portalOutlet.attachComponentPortal(portal);
}
/** Attach a template portal as content to this snackbar container. */
attachTemplatePortal(portal: TemplatePortal): EmbeddedViewRef {
+ this._assertNotAttached();
return this._portalOutlet.attachTemplatePortal(portal);
}
@@ -63,4 +65,11 @@ export class MdcSnackbarContainer extends BasePortalOutlet implements OnDestroy
this._onExit.complete();
});
}
+
+ /** Asserts that no content is already attached to the container. */
+ private _assertNotAttached() {
+ if (this._portalOutlet.hasAttached()) {
+ throw Error('Attempting to attach snackbar content after content is already attached');
+ }
+ }
}
diff --git a/packages/snackbar/snackbar.component.ts b/packages/snackbar/snackbar.component.ts
index ea02754b6..9923849d9 100644
--- a/packages/snackbar/snackbar.component.ts
+++ b/packages/snackbar/snackbar.component.ts
@@ -4,18 +4,13 @@ import {
Component,
ElementRef,
Inject,
- OnDestroy,
- OnInit,
- ViewChild,
ViewEncapsulation
} from '@angular/core';
import {LiveAnnouncer} from '@angular/cdk/a11y';
-import {MDCComponent} from '@angular-mdc/web/base';
-import {MdcSnackbarRef, MdcSnackbarDismissReason} from './snackbar-ref';
-import {MDC_SNACKBAR_DATA, MdcSnackbarConfig} from './snackbar-config';
-
-import {MDCSnackbarFoundation, MDCSnackbarAdapter} from '@material/snackbar';
+import {MdcSnackbarRef} from './snackbar-ref';
+import {MDC_SNACKBAR_DATA} from './snackbar-config';
+import {MdcSnackbarBase} from './snackbar-base';
@Component({
moduleId: module.id,
@@ -45,113 +40,13 @@ import {MDCSnackbarFoundation, MDCSnackbarAdapter} from '@material/snackbar';
encapsulation: ViewEncapsulation.None,
providers: [LiveAnnouncer]
})
-export class MdcSnackbarComponent extends MDCComponent implements OnInit, OnDestroy {
- @ViewChild('label', {static: true}) label!: ElementRef;
- @ViewChild('action', {static: false}) action?: ElementRef;
- @ViewChild('dismiss', {static: false}) dismiss?: ElementRef;
-
- get config(): MdcSnackbarConfig {
- return this.snackbarRef.componentInstance.snackbarConfig;
- }
-
- getDefaultFoundation() {
- const adapter: MDCSnackbarAdapter = {
- addClass: (className: string) => this._getHostElement().classList.add(className),
- removeClass: (className: string) => this._getHostElement().classList.remove(className),
- announce: () => this.label.nativeElement ? this._liveAnnouncer.announce(this.config.data.message,
- this.config.politeness, this.config.timeoutMs || MDCSnackbarFoundation.numbers.ARIA_LIVE_DELAY_MS) : {},
- notifyClosing: () => {},
- notifyOpened: () => {},
- notifyOpening: () => {},
- notifyClosed: (reason: MdcSnackbarDismissReason | string) => this.snackbarRef.dismiss(reason)
- };
- return new MDCSnackbarFoundation(adapter);
- }
-
+export class MdcSnackbarComponent extends MdcSnackbarBase {
constructor(
- private _changeDetectorRef: ChangeDetectorRef,
- private _liveAnnouncer: LiveAnnouncer,
- public elementRef: ElementRef,
- public snackbarRef: MdcSnackbarRef,
+ changeDetectorRef: ChangeDetectorRef,
+ liveAnnouncer: LiveAnnouncer,
+ elementRef: ElementRef,
+ snackbarRef: MdcSnackbarRef,
@Inject(MDC_SNACKBAR_DATA) public data: any) {
- super(elementRef);
- }
-
- ngOnInit(): void {
- this._changeDetectorRef.detectChanges();
-
- this._applyClasses();
- this._applyConfig();
- }
-
- ngOnDestroy(): void {
- if (this._foundation) {
- this._foundation.destroy();
- }
- }
-
- _onKeydown(evt: KeyboardEvent): void {
- this._foundation.handleKeyDown(evt);
- }
-
- _onActionClick(evt: MouseEvent): void {
- this._foundation.handleActionButtonClick(evt);
- }
-
- _onActionIconClick(evt: MouseEvent): void {
- this._foundation.handleActionIconClick(evt);
- }
-
- open(): void {
- this._foundation.open();
- }
-
- close(reason?: MdcSnackbarDismissReason): void {
- this._foundation.close(reason !== undefined ? reason.action ? 'action' : reason.dismiss ? 'dismiss' : '' : '');
- }
-
- private _applyClasses(): void {
- const classes = this.config.classes;
- if (classes) {
- if (classes instanceof Array) {
- this._getHostElement().classList.add(...this.config.classes as string[]);
- } else {
- this._getHostElement().classList.toggle(classes);
- }
- }
-
- const actionClasses = this.config.actionClasses;
- if (actionClasses && this.action) {
- if (actionClasses instanceof Array) {
- this.action.nativeElement.classList.add(...this.config.actionClasses as string[]);
- } else {
- this.action.nativeElement.classList.toggle(actionClasses);
- }
- }
-
- if (this.dismiss) {
- const dismissClasses = this.config.dismissClasses;
- if (dismissClasses) {
- if (dismissClasses instanceof Array) {
- this.dismiss.nativeElement.classList.add(...this.config.dismissClasses as string[]);
- } else {
- this.dismiss.nativeElement.classList.toggle(dismissClasses);
- }
- }
- }
- }
-
- private _applyConfig(): void {
- if (this.config.timeoutMs) {
- this._foundation.setTimeoutMs(this.config.timeoutMs);
- }
- if (this.config.dismiss) {
- this._foundation.setCloseOnEscape(this.config.closeOnEscape ? true : false);
- }
- }
-
- /** Retrieves the DOM element of the component host. */
- private _getHostElement(): HTMLElement {
- return this.elementRef.nativeElement;
+ super(changeDetectorRef, liveAnnouncer, elementRef, snackbarRef, data);
}
}
diff --git a/packages/snackbar/snackbar.ts b/packages/snackbar/snackbar.ts
index e9acd35e6..809be27b3 100644
--- a/packages/snackbar/snackbar.ts
+++ b/packages/snackbar/snackbar.ts
@@ -7,17 +7,19 @@ import {
Injector,
OnDestroy,
Optional,
- SkipSelf
+ SkipSelf,
+ TemplateRef
} from '@angular/core';
import {Overlay, OverlayRef} from '@angular/cdk/overlay';
-import {ComponentPortal, ComponentType, PortalInjector} from '@angular/cdk/portal';
+import {ComponentPortal, ComponentType, PortalInjector, TemplatePortal} from '@angular/cdk/portal';
import {MdcSnackbarModule} from './module';
import {MdcSnackbarRef} from './snackbar-ref';
-import {MdcSnackbarComponent} from './snackbar.component';
+import {MdcSnackbarBase} from './snackbar-base';
import {MDC_SNACKBAR_DATA, MdcSnackbarConfig} from './snackbar-config';
import {MdcSnackbarContainer} from './snackbar-container';
+import {MdcSnackbarComponent} from './snackbar.component';
/** Injection token that can be used to specify default snackbar. */
export const MDC_SNACKBAR_DEFAULT_OPTIONS =
@@ -36,7 +38,7 @@ export class MdcSnackbar implements OnDestroy {
/**
* Reference to the current snackbar in the view *at this level* (in the Angular injector tree).
* If there is a parent snack-bar service, all operations should delegate to that parent
- * via `_openedSnackBarRef`.
+ * via `_openedSnackbarRef`.
*/
private _snackBarRefAtThisLevel: MdcSnackbarRef | null = null;
@@ -72,6 +74,18 @@ export class MdcSnackbar implements OnDestroy {
return this._attach(component, config) as MdcSnackbarRef;
}
+ /**
+ * Creates and dispatches a snackbar with a custom template for the content, removing any
+ * currently opened snackbars.
+ *
+ * @param template Template to be instantiated.
+ * @param config Extra configuration for the snackbar.
+ */
+ openFromTemplate(template: TemplateRef, config?: MdcSnackbarConfig):
+ MdcSnackbarRef> {
+ return this._attach(template, config);
+ }
+
/**
* Opens a snackbar with a message and an optional action.
* @param message Message text.
@@ -129,7 +143,7 @@ export class MdcSnackbar implements OnDestroy {
/**
* Places a new component or a template as the content of the snackbar container.
*/
- private _attach(content: ComponentType, userConfig?: MdcSnackbarConfig):
+ private _attach(content: ComponentType | TemplateRef, userConfig?: MdcSnackbarConfig):
MdcSnackbarRef> {
const config = {...new MdcSnackbarConfig(), ...this._defaultConfig, ...userConfig};
@@ -137,12 +151,21 @@ export class MdcSnackbar implements OnDestroy {
const container = this._attachSnackbarContainer(overlayRef, config);
const snackbarRef = new MdcSnackbarRef>(container, overlayRef);
- const injector = this._createInjector(config, snackbarRef);
- const portal = new ComponentPortal(content, undefined, injector);
- const contentRef = container.attachComponentPortal(portal);
+ if (content instanceof TemplateRef) {
+ const portal = new TemplatePortal(content, null!, {
+ $implicit: config.data,
+ snackbarRef
+ } as any);
+
+ snackbarRef.instance = container.attachTemplatePortal(portal);
+ } else {
+ const injector = this._createInjector(config, snackbarRef);
+ const portal = new ComponentPortal(content, undefined, injector);
+ const contentRef = container.attachComponentPortal(portal);
- // We can't pass this via the injector, because the injector is created earlier.
- snackbarRef.instance = contentRef.instance;
+ // We can't pass this via the injector, because the injector is created earlier.
+ snackbarRef.instance = contentRef.instance;
+ }
this._loadListeners(snackbarRef);
this._openedSnackbarRef = snackbarRef;
@@ -162,9 +185,7 @@ export class MdcSnackbar implements OnDestroy {
}
});
- if (this._openedSnackbarRef) {
- this._openedSnackbarRef.dismiss();
- }
+ this._openedSnackbarRef?.dismiss();
}
/**
diff --git a/test/snackbar/snackbar.test.ts b/test/snackbar/snackbar.test.ts
index 96216b0a0..a82317957 100644
--- a/test/snackbar/snackbar.test.ts
+++ b/test/snackbar/snackbar.test.ts
@@ -68,10 +68,10 @@ describe('MdcSnackbar', () => {
viewContainerFixture.detectChanges();
expect(snackBarRef.instance instanceof MdcSnackbarComponent)
- .toBe(true, 'Expected the snack bar content component to be MdcSnackbarComponent');
+ .toBe(true, 'Expected the snackbar content component to be MdcSnackbarComponent');
expect(snackBarRef.instance.snackbarRef)
.toBe(snackBarRef,
- 'Expected the snack bar reference to be placed in the component instance');
+ 'Expected the snackbar reference to be placed in the component instance');
});
it('should open a snackbar with non-array CSS classes to apply', () => {
@@ -85,10 +85,10 @@ describe('MdcSnackbar', () => {
viewContainerFixture.detectChanges();
expect(snackBarRef.instance instanceof MdcSnackbarComponent)
- .toBe(true, 'Expected the snack bar content component to be MdcSnackbarComponent');
+ .toBe(true, 'Expected the snackbar content component to be MdcSnackbarComponent');
expect(snackBarRef.instance.snackbarRef)
.toBe(snackBarRef,
- 'Expected the snack bar reference to be placed in the component instance');
+ 'Expected the snackbar reference to be placed in the component instance');
});
it('should open a snackbar with an array of CSS classes to apply', () => {
@@ -102,10 +102,10 @@ describe('MdcSnackbar', () => {
viewContainerFixture.detectChanges();
expect(snackBarRef.instance instanceof MdcSnackbarComponent)
- .toBe(true, 'Expected the snack bar content component to be MdcSnackbarComponent');
+ .toBe(true, 'Expected the snackbar content component to be MdcSnackbarComponent');
expect(snackBarRef.instance.snackbarRef)
.toBe(snackBarRef,
- 'Expected the snack bar reference to be placed in the component instance');
+ 'Expected the snackbar reference to be placed in the component instance');
});
it('should open a snackbar with 10000 timeoutMs', () => {
@@ -136,12 +136,12 @@ describe('MdcSnackbar', () => {
viewContainerFixture.detectChanges();
expect(snackBarRef.instance instanceof MdcSnackbarComponent)
- .toBe(true, 'Expected the snack bar content component to be MdcSnackbarComponent');
+ .toBe(true, 'Expected the snackbar content component to be MdcSnackbarComponent');
expect(snackBarRef.instance.snackbarRef)
- .toBe(snackBarRef, 'Expected the snack bar reference to be placed in the component instance');
+ .toBe(snackBarRef, 'Expected the snackbar reference to be placed in the component instance');
});
- it('should dismiss the snack bar and remove itself from the view', fakeAsync(() => {
+ it('should dismiss the snackbar and remove itself from the view', fakeAsync(() => {
const config: MdcSnackbarConfig = {viewContainerRef: testViewContainerRef};
const dismissCompleteSpy = jasmine.createSpy('dismiss complete spy');
@@ -246,7 +246,7 @@ describe('MdcSnackbar', () => {
expect(viewContainerFixture.isStable()).toBe(true);
}));
- it('should dismiss the open snack bar on destroy', fakeAsync(() => {
+ it('should dismiss the open snackbar on destroy', fakeAsync(() => {
snackBar.open(simpleMessage);
viewContainerFixture.detectChanges();
expect(overlayContainerElement.childElementCount).toBeGreaterThan(0);
@@ -257,6 +257,72 @@ describe('MdcSnackbar', () => {
expect(overlayContainerElement.childElementCount).toBe(0);
}));
+
+ describe('with custom component', () => {
+ it('should open a custom component', () => {
+ const snackBarRef = snackBar.openFromComponent(BurritosNotification);
+
+ expect(snackBarRef.instance instanceof BurritosNotification)
+ .toBe(true, 'Expected the snackbar content component to be BurritosNotification');
+ expect(overlayContainerElement.textContent!.trim())
+ .toBe('Burritos are on the way.', 'Expected component to have the proper text.');
+ });
+
+ it('should inject the snackbar reference into the component', () => {
+ const snackBarRef = snackBar.openFromComponent(BurritosNotification);
+
+ expect(snackBarRef.instance.snackBarRef)
+ .toBe(snackBarRef, 'Expected component to have an injected snackbar reference.');
+ });
+
+ it('should be able to inject arbitrary user data', () => {
+ const snackBarRef = snackBar.openFromComponent(BurritosNotification, {
+ data: {
+ burritoType: 'Chimichanga'
+ }
+ });
+
+ expect(snackBarRef.instance.data).toBeTruthy('Expected component to have a data object.');
+ expect(snackBarRef.instance.data.burritoType)
+ .toBe('Chimichanga', 'Expected the injected data object to be the one the user provided.');
+ });
+ });
+
+ describe('with TemplateRef', () => {
+ let templateFixture: ComponentFixture;
+
+ beforeEach(() => {
+ templateFixture = TestBed.createComponent(ComponentWithTemplateRef);
+ templateFixture.detectChanges();
+ });
+
+ it('should be able to open a snackbar using a TemplateRef', () => {
+ templateFixture.componentInstance.localValue = 'Pizza';
+ snackBar.openFromTemplate(templateFixture.componentInstance.templateRef);
+ templateFixture.detectChanges();
+
+ const containerElement = overlayContainerElement.querySelector('mdc-snackbar-container')!;
+
+ expect(containerElement.textContent).toContain('Fries');
+ expect(containerElement.textContent).toContain('Pizza');
+
+ templateFixture.componentInstance.localValue = 'Pasta';
+ templateFixture.detectChanges();
+
+ expect(containerElement.textContent).toContain('Pasta');
+ });
+
+ it('should be able to pass in contextual data when opening with a TemplateRef', () => {
+ snackBar.openFromTemplate(templateFixture.componentInstance.templateRef, {
+ data: {value: 'Oranges'}
+ });
+ templateFixture.detectChanges();
+
+ const containerElement = overlayContainerElement.querySelector('mdc-snackbar-container')!;
+
+ expect(containerElement.textContent).toContain('Oranges');
+ });
+ });
});
describe('MdcSnackbar with parent MdcSnackbar', () => {
@@ -288,12 +354,12 @@ describe('MdcSnackbar with parent MdcSnackbar', () => {
overlayContainer.ngOnDestroy();
});
- it('should close snackBars opened by parent when opening from child', fakeAsync(() => {
+ it('should close snackbar opened by parent when opening from child', fakeAsync(() => {
parentSnackBar.open('Pizza');
fixture.detectChanges();
tick(110);
expect(overlayContainerElement.textContent)
- .toContain('Pizza', 'Expected a snackBar to be opened');
+ .toContain('Pizza', 'Expected a snackbar to be opened');
childSnackBar.open('Taco');
fixture.detectChanges();
@@ -304,12 +370,12 @@ describe('MdcSnackbar with parent MdcSnackbar', () => {
flush();
}));
- it('should close snackBars opened by child when opening from parent', fakeAsync(() => {
+ it('should close snackbar opened by child when opening from parent', fakeAsync(() => {
childSnackBar.open('Pizza');
fixture.detectChanges();
tick(110);
expect(overlayContainerElement.textContent)
- .toContain('Pizza', 'Expected a snackBar to be opened');
+ .toContain('Pizza', 'Expected a snackbar to be opened');
parentSnackBar.open('Taco');
fixture.detectChanges();
@@ -320,7 +386,7 @@ describe('MdcSnackbar with parent MdcSnackbar', () => {
flush();
}));
- it('should not dismiss parent snack bar if child is destroyed', fakeAsync(() => {
+ it('should not dismiss parent snackbar if child is destroyed', fakeAsync(() => {
parentSnackBar.open('Pizza');
fixture.detectChanges();
tick(110);
@@ -362,7 +428,7 @@ class ComponentWithChildViewContainer {
`,
})
class ComponentWithTemplateRef {
- @ViewChild(TemplateRef, {static: false}) templateRef: TemplateRef;
+ @ViewChild(TemplateRef) templateRef: TemplateRef;
localValue: string;
}
@@ -383,7 +449,7 @@ class ComponentThatProvidesMdcSnackBar {
}
/**
- * Simple component to open snack bars from.
+ * Simple component to open snackbars from.
* Create a real (non-test) NgModule as a workaround forRoot
* https://github.com/angular/angular/issues/10760
*/