mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Allow snackbar position on the screen. (#4045)
This commit is contained in:
@@ -3,6 +3,20 @@
|
||||
<div>
|
||||
Message: <md-form-field><input mdInput type="text" [(ngModel)]="message"></md-form-field>
|
||||
</div>
|
||||
<div>
|
||||
<div>Position in page: </div>
|
||||
<md-select [(ngModel)]="horizontalPosition">
|
||||
<md-option value="start">Start</md-option>
|
||||
<md-option value="end">End</md-option>
|
||||
<md-option value="left">Left</md-option>
|
||||
<md-option value="right">Right</md-option>
|
||||
<md-option value="center">Center</md-option>
|
||||
</md-select>
|
||||
<md-select [(ngModel)]="verticalPosition">
|
||||
<md-option value="top">Top</md-option>
|
||||
<md-option value="bottom">Bottom</md-option>
|
||||
</md-select>
|
||||
</div>
|
||||
<div>
|
||||
<md-checkbox [(ngModel)]="action">
|
||||
<p *ngIf="!action">Show button on snack bar</p>
|
||||
@@ -27,7 +41,6 @@
|
||||
</md-form-field>
|
||||
</md-checkbox>
|
||||
</div>
|
||||
|
||||
<p>
|
||||
<md-checkbox [(ngModel)]="addExtraClass">Add extra class to container</md-checkbox>
|
||||
</p>
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
import {Component, ViewEncapsulation} from '@angular/core';
|
||||
import {MdSnackBar, MdSnackBarConfig} from '@angular/material';
|
||||
import {
|
||||
MdSnackBar,
|
||||
MdSnackBarConfig,
|
||||
MdSnackBarHorizontalPosition,
|
||||
MdSnackBarVerticalPosition,
|
||||
Dir,
|
||||
} from '@angular/material';
|
||||
|
||||
@Component({
|
||||
moduleId: module.id,
|
||||
@@ -15,13 +21,18 @@ export class SnackBarDemo {
|
||||
setAutoHide: boolean = true;
|
||||
autoHide: number = 10000;
|
||||
addExtraClass: boolean = false;
|
||||
horizontalPosition: MdSnackBarHorizontalPosition = 'center';
|
||||
verticalPosition: MdSnackBarVerticalPosition = 'bottom';
|
||||
|
||||
constructor(public snackBar: MdSnackBar) { }
|
||||
constructor(public snackBar: MdSnackBar, private dir: Dir) { }
|
||||
|
||||
open() {
|
||||
let config = new MdSnackBarConfig();
|
||||
config.verticalPosition = this.verticalPosition;
|
||||
config.horizontalPosition = this.horizontalPosition;
|
||||
config.duration = this.autoHide;
|
||||
config.extraClasses = this.addExtraClass ? ['party'] : undefined;
|
||||
config.direction = this.dir.value;
|
||||
this.snackBar.open(this.message, this.action ? this.actionButtonLabel : undefined, config);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,12 @@ import {Direction} from '@angular/cdk/bidi';
|
||||
|
||||
export const MD_SNACK_BAR_DATA = new InjectionToken<any>('MdSnackBarData');
|
||||
|
||||
/** Possible values for horizontalPosition on MdSnackBarConfig. */
|
||||
export type MdSnackBarHorizontalPosition = 'start' | 'center' | 'end' | 'left' | 'right';
|
||||
|
||||
/** Possible values for verticalPosition on MdSnackBarConfig. */
|
||||
export type MdSnackBarVerticalPosition = 'top' | 'bottom';
|
||||
|
||||
/**
|
||||
* Configuration used when opening a snack-bar.
|
||||
*/
|
||||
@@ -36,4 +42,10 @@ export class MdSnackBarConfig {
|
||||
|
||||
/** Data being injected into the child component. */
|
||||
data?: any = null;
|
||||
|
||||
/** The horizontal position to place the snack bar. */
|
||||
horizontalPosition?: MdSnackBarHorizontalPosition = 'center';
|
||||
|
||||
/** The vertical position to place the snack bar. */
|
||||
verticalPosition?: MdSnackBarVerticalPosition = 'bottom';
|
||||
}
|
||||
|
||||
@@ -3,18 +3,36 @@
|
||||
$mat-snack-bar-padding: 14px 24px !default;
|
||||
$mat-snack-bar-min-width: 288px !default;
|
||||
$mat-snack-bar-max-width: 568px !default;
|
||||
$mat-snack-bar-spacing-margin: 24px !default;
|
||||
|
||||
|
||||
.mat-snack-bar-container {
|
||||
border-radius: 2px;
|
||||
box-sizing: content-box;
|
||||
display: block;
|
||||
margin: $mat-snack-bar-spacing-margin;
|
||||
max-width: $mat-snack-bar-max-width;
|
||||
min-width: $mat-snack-bar-min-width;
|
||||
padding: $mat-snack-bar-padding;
|
||||
// Initial transformation is applied to start snack bar out of view.
|
||||
// Initial transformation is applied to start snack bar out of view, below its target position.
|
||||
transform: translateY(100%);
|
||||
|
||||
/**
|
||||
* Removes margin of snack bars which are center positioned horizontally. This
|
||||
* is done to align snack bars to the edge of the view vertically to match spec.
|
||||
*/
|
||||
&.mat-snack-bar-center {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* To allow for animations from a 'top' vertical position to animate in a downward
|
||||
* direction, set the translation to start the snack bar above the target position.
|
||||
*/
|
||||
&.mat-snack-bar-top {
|
||||
transform: translateY(-100%);
|
||||
}
|
||||
|
||||
@include cdk-high-contrast {
|
||||
border: solid 1px;
|
||||
}
|
||||
|
||||
@@ -38,7 +38,7 @@ import {Subject} from 'rxjs/Subject';
|
||||
import {MdSnackBarConfig} from './snack-bar-config';
|
||||
|
||||
|
||||
export type SnackBarState = 'initial' | 'visible' | 'complete' | 'void';
|
||||
export type SnackBarState = 'visible' | 'hidden' | 'void';
|
||||
|
||||
// TODO(jelbourn): we can't use constants from animation.ts here because you can't use
|
||||
// a text interpolation in anything that is analyzed statically with ngc (for AoT compile).
|
||||
@@ -59,15 +59,22 @@ export const HIDE_ANIMATION = '195ms cubic-bezier(0.0,0.0,0.2,1)';
|
||||
host: {
|
||||
'role': 'alert',
|
||||
'class': 'mat-snack-bar-container',
|
||||
'[@state]': 'animationState',
|
||||
'[@state]': 'getAnimationState()',
|
||||
'(@state.done)': 'onAnimationEnd($event)'
|
||||
},
|
||||
animations: [
|
||||
trigger('state', [
|
||||
state('void, initial, complete', style({transform: 'translateY(100%)'})),
|
||||
state('visible', style({transform: 'translateY(0%)'})),
|
||||
transition('visible => complete', animate(HIDE_ANIMATION)),
|
||||
transition('initial => visible, void => visible', animate(SHOW_ANIMATION)),
|
||||
// Animation from top.
|
||||
state('visible-top', style({transform: 'translateY(0%)'})),
|
||||
state('hidden-top', style({transform: 'translateY(-100%)'})),
|
||||
transition('visible-top => hidden-top', animate(HIDE_ANIMATION)),
|
||||
transition('void => visible-top', animate(SHOW_ANIMATION)),
|
||||
// Animation from bottom.
|
||||
state('visible-bottom', style({transform: 'translateY(0%)'})),
|
||||
state('hidden-bottom', style({transform: 'translateY(100%)'})),
|
||||
transition('visible-bottom => hidden-bottom', animate(HIDE_ANIMATION)),
|
||||
transition('void => visible-bottom',
|
||||
animate(SHOW_ANIMATION)),
|
||||
])
|
||||
],
|
||||
})
|
||||
@@ -85,7 +92,7 @@ export class MdSnackBarContainer extends BasePortalHost implements OnDestroy {
|
||||
_onEnter: Subject<any> = new Subject();
|
||||
|
||||
/** The state of the snack bar animations. */
|
||||
animationState: SnackBarState = 'initial';
|
||||
private _animationState: SnackBarState;
|
||||
|
||||
/** The snack bar configuration. */
|
||||
snackBarConfig: MdSnackBarConfig;
|
||||
@@ -98,6 +105,14 @@ export class MdSnackBarContainer extends BasePortalHost implements OnDestroy {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current animation state both combining one of the possibilities from
|
||||
* SnackBarState and the vertical location.
|
||||
*/
|
||||
getAnimationState(): string {
|
||||
return `${this._animationState}-${this.snackBarConfig.verticalPosition}`;
|
||||
}
|
||||
|
||||
/** Attach a component portal as content to this snack bar container. */
|
||||
attachComponentPortal<T>(portal: ComponentPortal<T>): ComponentRef<T> {
|
||||
if (this._portalHost.hasAttached()) {
|
||||
@@ -112,6 +127,14 @@ export class MdSnackBarContainer extends BasePortalHost implements OnDestroy {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.snackBarConfig.horizontalPosition === 'center') {
|
||||
this._renderer.addClass(this._elementRef.nativeElement, 'mat-snack-bar-center');
|
||||
}
|
||||
|
||||
if (this.snackBarConfig.verticalPosition === 'top') {
|
||||
this._renderer.addClass(this._elementRef.nativeElement, 'mat-snack-bar-top');
|
||||
}
|
||||
|
||||
return this._portalHost.attachComponentPortal(portal);
|
||||
}
|
||||
|
||||
@@ -122,11 +145,11 @@ export class MdSnackBarContainer extends BasePortalHost implements OnDestroy {
|
||||
|
||||
/** Handle end of animations, updating the state of the snackbar. */
|
||||
onAnimationEnd(event: AnimationEvent) {
|
||||
if (event.toState === 'void' || event.toState === 'complete') {
|
||||
if (event.toState === 'void' || event.toState.startsWith('hidden')) {
|
||||
this._completeExit();
|
||||
}
|
||||
|
||||
if (event.toState === 'visible') {
|
||||
if (event.toState.startsWith('visible')) {
|
||||
// Note: we shouldn't use `this` inside the zone callback,
|
||||
// because it can cause a memory leak.
|
||||
const onEnter = this._onEnter;
|
||||
@@ -141,14 +164,14 @@ export class MdSnackBarContainer extends BasePortalHost implements OnDestroy {
|
||||
/** Begin animation of snack bar entrance into view. */
|
||||
enter(): void {
|
||||
if (!this._destroyed) {
|
||||
this.animationState = 'visible';
|
||||
this._animationState = 'visible';
|
||||
this._changeDetectorRef.detectChanges();
|
||||
}
|
||||
}
|
||||
|
||||
/** Begin animation of the snack bar exiting from view. */
|
||||
exit(): Observable<void> {
|
||||
this.animationState = 'complete';
|
||||
this._animationState = 'hidden';
|
||||
return this._onExit;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,8 +22,6 @@ import {
|
||||
} from './index';
|
||||
|
||||
|
||||
// TODO(josephperrott): Update tests to mock waiting for time to complete for animations.
|
||||
|
||||
describe('MdSnackBar', () => {
|
||||
let snackBar: MdSnackBar;
|
||||
let liveAnnouncer: LiveAnnouncer;
|
||||
@@ -66,7 +64,7 @@ describe('MdSnackBar', () => {
|
||||
});
|
||||
|
||||
it('should have the role of alert', () => {
|
||||
let config = {viewContainerRef: testViewContainerRef};
|
||||
let config: MdSnackBarConfig = {viewContainerRef: testViewContainerRef};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
|
||||
let containerElement = overlayContainerElement.querySelector('snack-bar-container')!;
|
||||
@@ -92,7 +90,7 @@ describe('MdSnackBar', () => {
|
||||
}));
|
||||
|
||||
it('should open a simple message with a button', () => {
|
||||
let config = {viewContainerRef: testViewContainerRef};
|
||||
let config: MdSnackBarConfig = {viewContainerRef: testViewContainerRef};
|
||||
let snackBarRef = snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
|
||||
viewContainerFixture.detectChanges();
|
||||
@@ -100,7 +98,8 @@ describe('MdSnackBar', () => {
|
||||
expect(snackBarRef.instance instanceof SimpleSnackBar)
|
||||
.toBe(true, 'Expected the snack bar content component to be SimpleSnackBar');
|
||||
expect(snackBarRef.instance.snackBarRef)
|
||||
.toBe(snackBarRef, 'Expected the snack bar reference to be placed in the component instance');
|
||||
.toBe(snackBarRef,
|
||||
'Expected the snack bar reference to be placed in the component instance');
|
||||
|
||||
let messageElement = overlayContainerElement.querySelector('snack-bar-container')!;
|
||||
expect(messageElement.textContent)
|
||||
@@ -115,7 +114,7 @@ describe('MdSnackBar', () => {
|
||||
});
|
||||
|
||||
it('should open a simple message with no button', () => {
|
||||
let config = {viewContainerRef: testViewContainerRef};
|
||||
let config: MdSnackBarConfig = {viewContainerRef: testViewContainerRef};
|
||||
let snackBarRef = snackBar.open(simpleMessage, undefined, config);
|
||||
|
||||
viewContainerFixture.detectChanges();
|
||||
@@ -133,7 +132,7 @@ describe('MdSnackBar', () => {
|
||||
});
|
||||
|
||||
it('should dismiss the snack bar and remove itself from the view', async(() => {
|
||||
let config = {viewContainerRef: testViewContainerRef};
|
||||
let config: MdSnackBarConfig = {viewContainerRef: testViewContainerRef};
|
||||
let dismissObservableCompleted = false;
|
||||
|
||||
let snackBarRef = snackBar.open(simpleMessage, undefined, config);
|
||||
@@ -183,33 +182,38 @@ describe('MdSnackBar', () => {
|
||||
}));
|
||||
|
||||
it('should set the animation state to visible on entry', () => {
|
||||
let config = {viewContainerRef: testViewContainerRef};
|
||||
let config: MdSnackBarConfig = {viewContainerRef: testViewContainerRef};
|
||||
let snackBarRef = snackBar.open(simpleMessage, undefined, config);
|
||||
|
||||
viewContainerFixture.detectChanges();
|
||||
expect(snackBarRef.containerInstance.animationState)
|
||||
.toBe('visible', `Expected the animation state would be 'visible'.`);
|
||||
expect(snackBarRef.containerInstance.getAnimationState())
|
||||
.toBe('visible-bottom', `Expected the animation state would be 'visible-bottom'.`);
|
||||
snackBarRef.dismiss();
|
||||
|
||||
viewContainerFixture.detectChanges();
|
||||
expect(snackBarRef.containerInstance.getAnimationState())
|
||||
.toBe('hidden-bottom', `Expected the animation state would be 'hidden-bottom'.`);
|
||||
});
|
||||
|
||||
it('should set the animation state to complete on exit', () => {
|
||||
let config = {viewContainerRef: testViewContainerRef};
|
||||
let config: MdSnackBarConfig = {viewContainerRef: testViewContainerRef};
|
||||
let snackBarRef = snackBar.open(simpleMessage, undefined, config);
|
||||
snackBarRef.dismiss();
|
||||
|
||||
viewContainerFixture.detectChanges();
|
||||
expect(snackBarRef.containerInstance.animationState)
|
||||
.toBe('complete', `Expected the animation state would be 'complete'.`);
|
||||
expect(snackBarRef.containerInstance.getAnimationState())
|
||||
.toBe('hidden-bottom', `Expected the animation state would be 'hidden-bottom'.`);
|
||||
});
|
||||
|
||||
it(`should set the old snack bar animation state to complete and the new snack bar animation
|
||||
state to visible on entry of new snack bar`, async(() => {
|
||||
let config = {viewContainerRef: testViewContainerRef};
|
||||
let config: MdSnackBarConfig = {viewContainerRef: testViewContainerRef};
|
||||
let snackBarRef = snackBar.open(simpleMessage, undefined, config);
|
||||
let dismissObservableCompleted = false;
|
||||
|
||||
viewContainerFixture.detectChanges();
|
||||
expect(snackBarRef.containerInstance.animationState)
|
||||
.toBe('visible', `Expected the animation state would be 'visible'.`);
|
||||
expect(snackBarRef.containerInstance.getAnimationState())
|
||||
.toBe('visible-bottom', `Expected the animation state would be 'visible-bottom'.`);
|
||||
|
||||
let config2 = {viewContainerRef: testViewContainerRef};
|
||||
let snackBarRef2 = snackBar.open(simpleMessage, undefined, config2);
|
||||
@@ -221,16 +225,17 @@ describe('MdSnackBar', () => {
|
||||
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(dismissObservableCompleted).toBe(true);
|
||||
expect(snackBarRef.containerInstance.animationState)
|
||||
.toBe('complete', `Expected the animation state would be 'complete'.`);
|
||||
expect(snackBarRef2.containerInstance.animationState)
|
||||
.toBe('visible', `Expected the animation state would be 'visible'.`);
|
||||
expect(snackBarRef.containerInstance.getAnimationState())
|
||||
.toBe('hidden-bottom', `Expected the animation state would be 'hidden-bottom'.`);
|
||||
expect(snackBarRef2.containerInstance.getAnimationState())
|
||||
.toBe('visible-bottom', `Expected the animation state would be 'visible-bottom'.`);
|
||||
});
|
||||
}));
|
||||
|
||||
it('should open a new snackbar after dismissing a previous snackbar', async(() => {
|
||||
let config = {viewContainerRef: testViewContainerRef};
|
||||
let config: MdSnackBarConfig = {viewContainerRef: testViewContainerRef};
|
||||
let snackBarRef = snackBar.open(simpleMessage, 'Dismiss', config);
|
||||
|
||||
viewContainerFixture.detectChanges();
|
||||
|
||||
snackBarRef.dismiss();
|
||||
@@ -243,7 +248,8 @@ describe('MdSnackBar', () => {
|
||||
|
||||
// Wait for the snackbar open animation to finish.
|
||||
viewContainerFixture.whenStable().then(() => {
|
||||
expect(snackBarRef.containerInstance.animationState).toBe('visible');
|
||||
expect(snackBarRef.containerInstance.getAnimationState())
|
||||
.toBe('visible-bottom', `Expected the animation state would be 'visible-bottom'.`);
|
||||
});
|
||||
});
|
||||
}));
|
||||
@@ -506,6 +512,240 @@ describe('MdSnackBar with parent MdSnackBar', () => {
|
||||
}));
|
||||
});
|
||||
|
||||
|
||||
describe('MdSnackBar Positioning', () => {
|
||||
let snackBar: MdSnackBar;
|
||||
let liveAnnouncer: LiveAnnouncer;
|
||||
let overlayContainerEl: HTMLElement;
|
||||
|
||||
let testViewContainerRef: ViewContainerRef;
|
||||
let viewContainerFixture: ComponentFixture<ComponentWithChildViewContainer>;
|
||||
|
||||
let simpleMessage = 'Burritos are here!';
|
||||
let simpleActionLabel = 'pickup';
|
||||
|
||||
beforeEach(async(() => {
|
||||
TestBed.configureTestingModule({
|
||||
imports: [MdSnackBarModule, SnackBarTestModule, NoopAnimationsModule],
|
||||
providers: [
|
||||
{provide: OverlayContainer, useFactory: () => {
|
||||
overlayContainerEl = document.createElement('div');
|
||||
return {getContainerElement: () => overlayContainerEl};
|
||||
}}
|
||||
],
|
||||
});
|
||||
TestBed.compileComponents();
|
||||
}));
|
||||
|
||||
beforeEach(inject([MdSnackBar, LiveAnnouncer], (sb: MdSnackBar, la: LiveAnnouncer) => {
|
||||
snackBar = sb;
|
||||
liveAnnouncer = la;
|
||||
}));
|
||||
|
||||
afterEach(() => {
|
||||
overlayContainerEl.innerHTML = '';
|
||||
liveAnnouncer.ngOnDestroy();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
viewContainerFixture = TestBed.createComponent(ComponentWithChildViewContainer);
|
||||
|
||||
viewContainerFixture.detectChanges();
|
||||
testViewContainerRef = viewContainerFixture.componentInstance.childViewContainer;
|
||||
});
|
||||
|
||||
it('should default to bottom center', () => {
|
||||
let config: MdSnackBarConfig = {};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeTruthy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeFalsy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('0px', 'Expected margin-bottom to be "0px"');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('', 'Expected margin-top to be ""');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('', 'Expected margin-right to be ""');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('', 'Expected margin-left to be ""');
|
||||
});
|
||||
|
||||
it('should be in the bottom left corner', () => {
|
||||
let config: MdSnackBarConfig = {
|
||||
verticalPosition: 'bottom',
|
||||
horizontalPosition: 'left'
|
||||
};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeFalsy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeFalsy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('0px', 'Expected margin-bottom to be "0px"');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('', 'Expected margin-top to be ""');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('', 'Expected margin-right to be ""');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('0px', 'Expected margin-left to be "0px"');
|
||||
});
|
||||
|
||||
it('should be in the bottom right corner', () => {
|
||||
let config: MdSnackBarConfig = {
|
||||
verticalPosition: 'bottom',
|
||||
horizontalPosition: 'right'
|
||||
};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeFalsy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeFalsy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('0px', 'Expected margin-bottom to be "0px"');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('', 'Expected margin-top to be ""');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('0px', 'Expected margin-right to be "0px"');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('', 'Expected margin-left to be ""');
|
||||
});
|
||||
|
||||
it('should be in the bottom center', () => {
|
||||
let config: MdSnackBarConfig = {
|
||||
verticalPosition: 'bottom',
|
||||
horizontalPosition: 'center'
|
||||
};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeTruthy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeFalsy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('0px', 'Expected margin-bottom to be "0px"');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('', 'Expected margin-top to be ""');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('', 'Expected margin-right to be ""');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('', 'Expected margin-left to be ""');
|
||||
});
|
||||
|
||||
it('should be in the top left corner', () => {
|
||||
let config: MdSnackBarConfig = {
|
||||
verticalPosition: 'top',
|
||||
horizontalPosition: 'left'
|
||||
};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeFalsy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeTruthy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('', 'Expected margin-bottom to be ""');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('0px', 'Expected margin-top to be "0px"');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('', 'Expected margin-right to be ""');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('0px', 'Expected margin-left to be "0px"');
|
||||
});
|
||||
|
||||
it('should be in the top right corner', () => {
|
||||
let config: MdSnackBarConfig = {
|
||||
verticalPosition: 'top',
|
||||
horizontalPosition: 'right'
|
||||
};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeFalsy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeTruthy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('', 'Expected margin-bottom to be ""');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('0px', 'Expected margin-top to be "0px"');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('0px', 'Expected margin-right to be "0px"');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('', 'Expected margin-left to be ""');
|
||||
});
|
||||
|
||||
it('should be in the top center', () => {
|
||||
let config: MdSnackBarConfig = {
|
||||
verticalPosition: 'top',
|
||||
horizontalPosition: 'center'
|
||||
};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeTruthy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeTruthy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('', 'Expected margin-bottom to be ""');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('0px', 'Expected margin-top to be "0px"');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('', 'Expected margin-right to be ""');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('', 'Expected margin-left to be ""');
|
||||
});
|
||||
|
||||
it('should handle start based on direction (rtl)', () => {
|
||||
let config: MdSnackBarConfig = {
|
||||
verticalPosition: 'top',
|
||||
horizontalPosition: 'start',
|
||||
direction: 'rtl',
|
||||
};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeFalsy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeTruthy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('', 'Expected margin-bottom to be ""');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('0px', 'Expected margin-top to be "0px"');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('0px', 'Expected margin-right to be "0px"');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('', 'Expected margin-left to be ""');
|
||||
});
|
||||
|
||||
it('should handle start based on direction (ltr)', () => {
|
||||
let config: MdSnackBarConfig = {
|
||||
verticalPosition: 'top',
|
||||
horizontalPosition: 'start',
|
||||
direction: 'ltr',
|
||||
};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeFalsy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeTruthy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('', 'Expected margin-bottom to be ""');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('0px', 'Expected margin-top to be "0px"');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('', 'Expected margin-right to be ""');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('0px', 'Expected margin-left to be "0px"');
|
||||
});
|
||||
|
||||
|
||||
it('should handle end based on direction (rtl)', () => {
|
||||
let config: MdSnackBarConfig = {
|
||||
verticalPosition: 'top',
|
||||
horizontalPosition: 'end',
|
||||
direction: 'rtl',
|
||||
};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeFalsy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeTruthy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('', 'Expected margin-bottom to be ""');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('0px', 'Expected margin-top to be "0px"');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('', 'Expected margin-right to be ""');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('0px', 'Expected margin-left to be "0px"');
|
||||
});
|
||||
|
||||
it('should handle end based on direction (ltr)', () => {
|
||||
let config: MdSnackBarConfig = {
|
||||
verticalPosition: 'top',
|
||||
horizontalPosition: 'end',
|
||||
direction: 'ltr',
|
||||
};
|
||||
snackBar.open(simpleMessage, simpleActionLabel, config);
|
||||
let containerEl = overlayContainerEl.querySelector('snack-bar-container') as HTMLElement;
|
||||
let overlayPaneEl = overlayContainerEl.querySelector('.cdk-overlay-pane') as HTMLElement;
|
||||
|
||||
expect(containerEl.classList.contains('mat-snack-bar-center')).toBeFalsy();
|
||||
expect(containerEl.classList.contains('mat-snack-bar-top')).toBeTruthy();
|
||||
expect(overlayPaneEl.style.marginBottom).toBe('', 'Expected margin-bottom to be ""');
|
||||
expect(overlayPaneEl.style.marginTop).toBe('0px', 'Expected margin-top to be "0px"');
|
||||
expect(overlayPaneEl.style.marginRight).toBe('0px', 'Expected margin-right to be "0px"');
|
||||
expect(overlayPaneEl.style.marginLeft).toBe('', 'Expected margin-left to be ""');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
@Directive({selector: 'dir-with-view-container'})
|
||||
class DirectiveWithViewContainer {
|
||||
constructor(public viewContainerRef: ViewContainerRef) { }
|
||||
|
||||
@@ -153,11 +153,32 @@ export class MdSnackBar {
|
||||
* @param config The user-specified snack bar config.
|
||||
*/
|
||||
private _createOverlay(config: MdSnackBarConfig): OverlayRef {
|
||||
const state = new OverlayState({
|
||||
direction: config.direction,
|
||||
positionStrategy: this._overlay.position().global().centerHorizontally().bottom('0')
|
||||
});
|
||||
const state = new OverlayState();
|
||||
state.direction = config.direction;
|
||||
|
||||
let positionStrategy = this._overlay.position().global();
|
||||
// Set horizontal position.
|
||||
const isRtl = config.direction === 'rtl';
|
||||
const isLeft = (
|
||||
config.horizontalPosition === 'left' ||
|
||||
(config.horizontalPosition === 'start' && !isRtl) ||
|
||||
(config.horizontalPosition === 'end' && isRtl));
|
||||
const isRight = !isLeft && config.horizontalPosition !== 'center';
|
||||
if (isLeft) {
|
||||
positionStrategy.left('0');
|
||||
} else if (isRight) {
|
||||
positionStrategy.right('0');
|
||||
} else {
|
||||
positionStrategy.centerHorizontally();
|
||||
}
|
||||
// Set horizontal position.
|
||||
if (config.verticalPosition === 'top') {
|
||||
positionStrategy.top('0');
|
||||
} else {
|
||||
positionStrategy.bottom('0');
|
||||
}
|
||||
|
||||
state.positionStrategy = positionStrategy;
|
||||
return this._overlay.create(state);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user