From 540226c3f96ac72f4f9c1e34503e27d902230f1c Mon Sep 17 00:00:00 2001 From: Kristiyan Kostadinov Date: Thu, 19 Apr 2018 11:44:19 -0600 Subject: [PATCH] feat(overlay): allow multiple classes to be assigned to the backdrop (#10531) Adds the ability to pass in an array of CSS classes to the `backdropClass`. Fixes #10529. --- src/cdk/overlay/overlay-config.ts | 2 +- src/cdk/overlay/overlay-ref.ts | 23 ++++++++++++++--------- src/cdk/overlay/overlay.spec.ts | 14 +++++++++++++- 3 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/cdk/overlay/overlay-config.ts b/src/cdk/overlay/overlay-config.ts index 48040af21ed..88f116a86e6 100644 --- a/src/cdk/overlay/overlay-config.ts +++ b/src/cdk/overlay/overlay-config.ts @@ -27,7 +27,7 @@ export class OverlayConfig { hasBackdrop?: boolean = false; /** Custom class to add to the backdrop */ - backdropClass?: string = 'cdk-overlay-dark-backdrop'; + backdropClass?: string | string[] = 'cdk-overlay-dark-backdrop'; /** The width of the overlay panel. If a number is provided, pixel units are assumed. */ width?: number | string; diff --git a/src/cdk/overlay/overlay-ref.ts b/src/cdk/overlay/overlay-ref.ts index 83eb45f9c66..6c1c865280d 100644 --- a/src/cdk/overlay/overlay-ref.ts +++ b/src/cdk/overlay/overlay-ref.ts @@ -13,7 +13,7 @@ import {Observable, Subject} from 'rxjs'; import {take} from 'rxjs/operators'; import {OverlayKeyboardDispatcher} from './keyboard/overlay-keyboard-dispatcher'; import {OverlayConfig} from './overlay-config'; -import {coerceCssPixelValue} from '@angular/cdk/coercion'; +import {coerceCssPixelValue, coerceArray} from '@angular/cdk/coercion'; /** An object where all of its properties cannot be written. */ @@ -115,12 +115,7 @@ export class OverlayRef implements PortalOutlet { } if (this._config.panelClass) { - // We can't do a spread here, because IE doesn't support setting multiple classes. - if (Array.isArray(this._config.panelClass)) { - this._config.panelClass.forEach(cssClass => this._pane.classList.add(cssClass)); - } else { - this._pane.classList.add(this._config.panelClass); - } + this._toggleClasses(this._pane, this._config.panelClass, true); } // Only emit the `attachments` event once all other setup is done. @@ -292,7 +287,7 @@ export class OverlayRef implements PortalOutlet { this._backdropElement.classList.add('cdk-overlay-backdrop'); if (this._config.backdropClass) { - this._backdropElement.classList.add(this._config.backdropClass); + this._toggleClasses(this._backdropElement, this._config.backdropClass, true); } // Insert the backdrop before the pane in the DOM order, @@ -353,7 +348,7 @@ export class OverlayRef implements PortalOutlet { backdropToDetach.classList.remove('cdk-overlay-backdrop-showing'); if (this._config.backdropClass) { - backdropToDetach.classList.remove(this._config.backdropClass); + this._toggleClasses(backdropToDetach, this._config.backdropClass, false); } backdropToDetach.addEventListener('transitionend', finishDetach); @@ -368,6 +363,16 @@ export class OverlayRef implements PortalOutlet { this._ngZone.runOutsideAngular(() => setTimeout(finishDetach, 500)); } } + + /** Toggles a single CSS class or an array of classes on an element. */ + private _toggleClasses(element: HTMLElement, cssClasses: string | string[], isAdd: boolean) { + const classList = element.classList; + + coerceArray(cssClasses).forEach(cssClass => { + // We can't do a spread here, because IE doesn't support setting multiple classes. + isAdd ? classList.add(cssClass) : classList.remove(cssClass); + }); + } } diff --git a/src/cdk/overlay/overlay.spec.ts b/src/cdk/overlay/overlay.spec.ts index a2121b758a2..a9eac6126c5 100644 --- a/src/cdk/overlay/overlay.spec.ts +++ b/src/cdk/overlay/overlay.spec.ts @@ -442,7 +442,7 @@ describe('Overlay', () => { expect(backdrop.classList).toContain('cdk-overlay-dark-backdrop'); }); - it('should apply a custom overlay backdrop class', () => { + it('should apply a custom class to the backdrop', () => { config.backdropClass = 'cdk-overlay-transparent-backdrop'; let overlayRef = overlay.create(config); @@ -453,6 +453,18 @@ describe('Overlay', () => { expect(backdrop.classList).toContain('cdk-overlay-transparent-backdrop'); }); + it('should apply multiple custom classes to the overlay', () => { + config.backdropClass = ['custom-class-1', 'custom-class-2']; + + let overlayRef = overlay.create(config); + overlayRef.attach(componentPortal); + viewContainerFixture.detectChanges(); + + let backdrop = overlayContainerElement.querySelector('.cdk-overlay-backdrop') as HTMLElement; + expect(backdrop.classList).toContain('custom-class-1'); + expect(backdrop.classList).toContain('custom-class-2'); + }); + it('should disable the pointer events of a backdrop that is being removed', () => { let overlayRef = overlay.create(config); overlayRef.attach(componentPortal);