Skip to content

Commit a944f6e

Browse files
authored
feat(overlay): replace OverlayContainer themeClass w/ addClass/removeClass methods (#6975)
BREAKING CHANGE: Now that the Overlay is part of the cdk rather than Angular Material directly, the `themeClass` property has been removed. To add a class to the overlay for theming, you can do ```ts overlayContainer.getContainerElement().classList.add('my-theme-class'); ```
1 parent 2b0315d commit a944f6e

File tree

5 files changed

+22
-76
lines changed

5 files changed

+22
-76
lines changed

guides/theming.md

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ Since certain components (e.g. menu, select, dialog, etc.) are inside of a globa
169169
an additional step is required for those components to be affected by the theme's css class selector
170170
(`.unicorn-dark-theme` in the example above).
171171

172-
To do this, you can specify a `themeClass` on the global overlay container. For the example above,
172+
To do this, you can add the appropriate class to the global overlay container. For the example above,
173173
this would look like:
174174
```ts
175175
import {OverlayContainer} from '@angular/material';
@@ -179,14 +179,11 @@ import {OverlayContainer} from '@angular/material';
179179
})
180180
export class UnicornCandyAppModule {
181181
constructor(overlayContainer: OverlayContainer) {
182-
overlayContainer.themeClass = 'unicorn-dark-theme';
182+
overlayContainer.getContainerElement().classList.add('unicorn-dark-theme');
183183
}
184184
}
185185
```
186186

187-
The `themeClass` of the `OverlayContainer` can be changed at any time to change the active theme
188-
class.
189-
190187
#### Theming only certain components
191188
The `angular-material-theme` mixin will output styles for [all components in the library](https://github.com/angular/material2/blob/master/src/lib/core/theming/_all-theme.scss).
192189
If you are only using a subset of the components (or if you want to change the theme for specific

src/cdk/overlay/overlay-container.spec.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ describe('OverlayContainer', () => {
2626
overlayContainer = oc;
2727
}));
2828

29+
afterEach(() => {
30+
overlayContainer.ngOnDestroy();
31+
});
32+
2933
it('should remove the overlay container element from the DOM on destruction', () => {
3034
const fixture = TestBed.createComponent(TestComponentWithTemplatePortals);
3135

@@ -43,6 +47,19 @@ describe('OverlayContainer', () => {
4347
expect(document.querySelector('.cdk-overlay-container'))
4448
.toBeNull('Expected the overlay container *not* to be in the DOM after destruction');
4549
});
50+
51+
it('should add and remove css classes from the container element', () => {
52+
overlayContainer.getContainerElement().classList.add('commander-shepard');
53+
54+
const containerElement = document.querySelector('.cdk-overlay-container')!;
55+
expect(containerElement.classList.contains('commander-shepard'))
56+
.toBe(true, 'Expected the overlay container to have class "commander-shepard"');
57+
58+
overlayContainer.getContainerElement().classList.remove('commander-shepard');
59+
60+
expect(containerElement.classList.contains('commander-shepard'))
61+
.toBe(false, 'Expected the overlay container not to have class "commander-shepard"');
62+
});
4663
});
4764

4865
/** Test-bed component that contains a TempatePortal and an ElementRef. */

src/cdk/overlay/overlay-container.ts

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -17,34 +17,14 @@ import {Injectable, Optional, SkipSelf, OnDestroy} from '@angular/core';
1717
export class OverlayContainer implements OnDestroy {
1818
protected _containerElement: HTMLElement;
1919

20-
private _themeClass: string;
21-
22-
/**
23-
* Base theme to be applied to all overlay-based components.
24-
*/
25-
get themeClass(): string { return this._themeClass; }
26-
set themeClass(value: string) {
27-
if (this._containerElement) {
28-
if (this._themeClass) {
29-
this._containerElement.classList.remove(this._themeClass);
30-
}
31-
32-
if (value) {
33-
this._containerElement.classList.add(value);
34-
}
35-
}
36-
37-
this._themeClass = value;
38-
}
39-
4020
ngOnDestroy() {
4121
if (this._containerElement && this._containerElement.parentNode) {
4222
this._containerElement.parentNode.removeChild(this._containerElement);
4323
}
4424
}
4525

4626
/**
47-
* This method returns the overlay container element. It will lazily
27+
* This method returns the overlay container element. It will lazily
4828
* create the element the first time it is called to facilitate using
4929
* the container in non-browser environments.
5030
* @returns the container element
@@ -62,10 +42,6 @@ export class OverlayContainer implements OnDestroy {
6242
let container = document.createElement('div');
6343
container.classList.add('cdk-overlay-container');
6444

65-
if (this._themeClass) {
66-
container.classList.add(this._themeClass);
67-
}
68-
6945
document.body.appendChild(container);
7046
this._containerElement = container;
7147
}

src/cdk/overlay/overlay.spec.ts

Lines changed: 0 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -469,44 +469,6 @@ describe('Overlay', () => {
469469
});
470470
});
471471

472-
describe('OverlayContainer theming', () => {
473-
let overlayContainer: OverlayContainer;
474-
let overlayContainerElement: HTMLElement;
475-
476-
beforeEach(async(() => {
477-
TestBed.configureTestingModule({ imports: [OverlayContainerThemingTestModule] });
478-
TestBed.compileComponents();
479-
}));
480-
481-
beforeEach(inject([OverlayContainer], (o: OverlayContainer) => {
482-
overlayContainer = o;
483-
overlayContainerElement = overlayContainer.getContainerElement();
484-
}));
485-
486-
afterEach(() => {
487-
overlayContainerElement.parentNode!.removeChild(overlayContainerElement);
488-
});
489-
490-
it('should be able to set a theme on the overlay container', () => {
491-
overlayContainer.themeClass = 'my-theme';
492-
expect(overlayContainerElement.classList).toContain('my-theme');
493-
});
494-
495-
it('should clear any previously-set themes when a new theme is set', () => {
496-
overlayContainer.themeClass = 'initial-theme';
497-
expect(overlayContainerElement.classList).toContain('initial-theme');
498-
499-
overlayContainer.themeClass = 'new-theme';
500-
expect(overlayContainerElement.classList).not.toContain('initial-theme');
501-
expect(overlayContainerElement.classList).toContain('new-theme');
502-
});
503-
504-
it('should not throw when switching from a blank theme', () => {
505-
overlayContainer.themeClass = '';
506-
expect(() => overlayContainer.themeClass = 'new-theme').not.toThrow();
507-
});
508-
});
509-
510472
/** Simple component for testing ComponentPortal. */
511473
@Component({
512474
selector: 'pizza',
@@ -534,12 +496,6 @@ const TEST_COMPONENTS = [PizzaMsg, TestComponentWithTemplatePortals];
534496
})
535497
class OverlayTestModule { }
536498

537-
/** Component for testing the overlay container theming. */
538-
@NgModule({
539-
imports: [OverlayModule, PortalModule],
540-
})
541-
class OverlayContainerThemingTestModule { }
542-
543499
class FakePositionStrategy implements PositionStrategy {
544500
element: HTMLElement;
545501

src/demo-app/demo-app/demo-app.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,10 @@ export class DemoApp {
109109

110110
if (this.dark) {
111111
this._renderer.addClass(this._element.nativeElement, darkThemeClass);
112-
this._overlayContainer.themeClass = darkThemeClass;
112+
this._overlayContainer.getContainerElement().classList.add(darkThemeClass);
113113
} else {
114114
this._renderer.removeClass(this._element.nativeElement, darkThemeClass);
115-
this._overlayContainer.themeClass = '';
115+
this._overlayContainer.getContainerElement().classList.remove(darkThemeClass);
116116
}
117117
}
118118
}

0 commit comments

Comments
 (0)