Skip to content

Commit f31134e

Browse files
committed
feat(theming): log a warning if core theme isn't loaded
Checks the user's loaded stylesheets and logs a warning if the Material core theme isn't loaded. Fixes #2828.
1 parent 3b6cab0 commit f31134e

File tree

27 files changed

+130
-39
lines changed

27 files changed

+130
-39
lines changed

src/lib/autocomplete/index.ts

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
import {ModuleWithProviders, NgModule} from '@angular/core';
2-
import {MdOptionModule, OverlayModule, OVERLAY_PROVIDERS, CompatibilityModule} from '../core';
2+
import {
3+
MdOptionModule,
4+
OverlayModule,
5+
OVERLAY_PROVIDERS,
6+
CompatibilityModule,
7+
MdThemeCheckModule
8+
} from '../core';
39
import {MdAutocomplete} from './autocomplete';
410
import {MdAutocompleteTrigger} from './autocomplete-trigger';
511
export * from './autocomplete';
612
export * from './autocomplete-trigger';
713

814
@NgModule({
9-
imports: [MdOptionModule, OverlayModule, CompatibilityModule],
15+
imports: [MdOptionModule, OverlayModule, CompatibilityModule, MdThemeCheckModule],
1016
exports: [MdAutocomplete, MdOptionModule, MdAutocompleteTrigger, CompatibilityModule],
1117
declarations: [MdAutocomplete, MdAutocompleteTrigger],
1218
})

src/lib/button-toggle/button-toggle.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
coerceBooleanProperty,
2626
UNIQUE_SELECTION_DISPATCHER_PROVIDER,
2727
CompatibilityModule,
28+
MdThemeCheckModule,
2829
} from '../core';
2930

3031
/** Acceptable types for a button toggle. */
@@ -464,7 +465,7 @@ export class MdButtonToggle implements OnInit {
464465

465466

466467
@NgModule({
467-
imports: [FormsModule, CompatibilityModule],
468+
imports: [FormsModule, CompatibilityModule, MdThemeCheckModule],
468469
exports: [
469470
MdButtonToggleGroup,
470471
MdButtonToggleGroupMultiple,

src/lib/button/button.ts

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,12 @@ import {
1010
ModuleWithProviders,
1111
} from '@angular/core';
1212
import {CommonModule} from '@angular/common';
13-
import {MdRippleModule, coerceBooleanProperty, CompatibilityModule} from '../core';
13+
import {
14+
MdRippleModule,
15+
coerceBooleanProperty,
16+
CompatibilityModule,
17+
MdThemeCheckModule
18+
} from '../core';
1419

1520

1621
// TODO(jelbourn): Make the `isMouseDown` stuff done with one global listener.
@@ -164,7 +169,7 @@ export class MdAnchor extends MdButton {
164169

165170

166171
@NgModule({
167-
imports: [CommonModule, MdRippleModule, CompatibilityModule],
172+
imports: [CommonModule, MdRippleModule, CompatibilityModule, MdThemeCheckModule],
168173
exports: [MdButton, MdAnchor, CompatibilityModule],
169174
declarations: [MdButton, MdAnchor],
170175
})

src/lib/card/card.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import {
66
ChangeDetectionStrategy,
77
Directive
88
} from '@angular/core';
9-
import {CompatibilityModule} from '../core';
9+
import {CompatibilityModule, MdThemeCheckModule} from '../core';
1010

1111

1212
/**
@@ -101,7 +101,7 @@ export class MdCardTitleGroup {}
101101

102102

103103
@NgModule({
104-
imports: [CompatibilityModule],
104+
imports: [CompatibilityModule, MdThemeCheckModule],
105105
exports: [
106106
MdCard,
107107
MdCardHeader,

src/lib/checkbox/checkbox.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
import {CommonModule} from '@angular/common';
1717
import {NG_VALUE_ACCESSOR, ControlValueAccessor} from '@angular/forms';
1818
import {coerceBooleanProperty} from '../core/coercion/boolean-property';
19-
import {MdRippleModule, CompatibilityModule} from '../core';
19+
import {MdRippleModule, CompatibilityModule, MdThemeCheckModule} from '../core';
2020

2121

2222
/** Monotonically increasing integer used to auto-generate unique ids for checkbox components. */
@@ -403,7 +403,7 @@ export class MdCheckbox implements ControlValueAccessor {
403403

404404

405405
@NgModule({
406-
imports: [CommonModule, MdRippleModule, CompatibilityModule],
406+
imports: [CommonModule, MdRippleModule, CompatibilityModule, MdThemeCheckModule],
407407
exports: [MdCheckbox, CompatibilityModule],
408408
declarations: [MdCheckbox],
409409
})

src/lib/chips/chip-list.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import {
1111
ViewEncapsulation
1212
} from '@angular/core';
1313

14+
import {MdThemeCheckModule} from '../core';
1415
import {MdChip} from './chip';
1516
import {FocusKeyManager} from '../core/a11y/focus-key-manager';
1617
import {coerceBooleanProperty} from '../core/coercion/boolean-property';
@@ -210,7 +211,7 @@ export class MdChipList implements AfterContentInit {
210211
}
211212

212213
@NgModule({
213-
imports: [],
214+
imports: [MdThemeCheckModule],
214215
exports: [MdChipList, MdChip],
215216
declarations: [MdChipList, MdChip]
216217
})

src/lib/core/_core.scss

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,14 +26,21 @@
2626

2727
// Mixin that renders all of the core styles that depend on the theme.
2828
@mixin md-core-theme($theme) {
29-
@include md-ripple-theme($theme);
30-
@include md-option-theme($theme);
31-
@include md-pseudo-checkbox-theme($theme);
29+
// Marker that is used to determine whether the user has added a theme to their page.
30+
// Note that only the selector is being used, but we add a property, in order to avoid
31+
// it being removed by minifiers.
32+
.md-theme-loaded-marker {
33+
color: #000;
34+
}
3235

3336
// Wrapper element that provides the theme background when the
3437
// user's content isn't inside of a `md-sidenav-container`.
3538
.md-app-background {
3639
$background: map-get($theme, background);
3740
background-color: md-color($background, background);
3841
}
42+
43+
@include md-ripple-theme($theme);
44+
@include md-option-theme($theme);
45+
@include md-pseudo-checkbox-theme($theme);
3946
}

src/lib/core/core.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {PortalModule} from './portal/portal-directives';
88
import {OverlayModule} from './overlay/overlay-directives';
99
import {A11yModule} from './a11y/index';
1010
import {MdSelectionModule} from './selection/index';
11+
import {MdThemeCheckModule} from './theming/theme-check';
1112

1213

1314
// RTL
@@ -86,6 +87,9 @@ export {isFakeMousedownFromScreenReader} from './a11y/fake-mousedown';
8687

8788
export {A11yModule} from './a11y/index';
8889

90+
// Theming check
91+
export {MdThemeCheckModule} from './theming/theme-check';
92+
8993
export {
9094
UniqueSelectionDispatcher,
9195
UniqueSelectionDispatcherListener,
@@ -137,6 +141,7 @@ export {CompatibilityModule, NoConflictStyleCompatibilityMode} from './compatibi
137141
A11yModule,
138142
MdOptionModule,
139143
MdSelectionModule,
144+
MdThemeCheckModule,
140145
],
141146
exports: [
142147
MdLineModule,
@@ -148,6 +153,7 @@ export {CompatibilityModule, NoConflictStyleCompatibilityMode} from './compatibi
148153
A11yModule,
149154
MdOptionModule,
150155
MdSelectionModule,
156+
MdThemeCheckModule,
151157
],
152158
})
153159
export class MdCoreModule {

src/lib/core/theming/theme-check.ts

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import {NgModule, isDevMode} from '@angular/core';
2+
3+
/**
4+
* Module that verifies that the user has loaded the core theming file,
5+
* without which most Material module won't work as expected.
6+
* @docs-private
7+
*/
8+
@NgModule()
9+
export class MdThemeCheckModule {
10+
constructor() {
11+
if (!isDevMode() || typeof document === 'undefined') {
12+
return;
13+
}
14+
15+
for (let i = 0; i < document.styleSheets.length; i++) {
16+
// The try/catch is needed, because some browsers can throw a security
17+
// error when accessing the `cssRules` from another domain.
18+
try {
19+
let rules = (document.styleSheets.item(i) as CSSStyleSheet).cssRules;
20+
21+
if (rules) {
22+
for (let j = 0; j < rules.length; j++) {
23+
let selector = (rules.item(j) as CSSStyleRule).selectorText;
24+
25+
if (selector && selector.includes('.md-theme-loaded-marker')) {
26+
return;
27+
}
28+
}
29+
}
30+
} catch (e) { }
31+
}
32+
33+
console.warn(
34+
'Could not find Angular Material core theme. Most Material ' +
35+
'components may not work as expected. For more info refer ' +
36+
'to the theming guide: https://github.com/angular/material2/blob/master/guides/theming.md'
37+
);
38+
}
39+
}

src/lib/dialog/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import {
44
PortalModule,
55
A11yModule,
66
CompatibilityModule,
7+
MdThemeCheckModule,
78
} from '../core';
89
import {MdDialog} from './dialog';
910
import {MdDialogContainer} from './dialog-container';
@@ -21,6 +22,7 @@ import {
2122
PortalModule,
2223
A11yModule,
2324
CompatibilityModule,
25+
MdThemeCheckModule,
2426
],
2527
exports: [
2628
MdDialogContainer,

src/lib/grid-list/grid-list.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {MdGridTile, MdGridTileText} from './grid-tile';
1616
import {TileCoordinator} from './tile-coordinator';
1717
import {TileStyler, FitTileStyler, RatioTileStyler, FixedTileStyler} from './tile-styler';
1818
import {MdGridListColsError} from './grid-list-errors';
19-
import {Dir, MdLineModule, CompatibilityModule} from '../core';
19+
import {Dir, MdLineModule, CompatibilityModule, MdThemeCheckModule} from '../core';
2020
import {
2121
coerceToString,
2222
coerceToNumber,
@@ -144,7 +144,7 @@ export class MdGridList implements OnInit, AfterContentChecked {
144144

145145

146146
@NgModule({
147-
imports: [MdLineModule, CompatibilityModule],
147+
imports: [MdLineModule, CompatibilityModule, MdThemeCheckModule],
148148
exports: [
149149
MdGridList,
150150
MdGridTile,

src/lib/icon/icon.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import {
1616
} from '@angular/core';
1717
import {HttpModule, Http} from '@angular/http';
1818
import {DomSanitizer} from '@angular/platform-browser';
19-
import {MdError, CompatibilityModule} from '../core';
19+
import {MdError, CompatibilityModule, MdThemeCheckModule} from '../core';
2020
import {MdIconRegistry} from './icon-registry';
2121
export {MdIconRegistry} from './icon-registry';
2222

@@ -260,7 +260,7 @@ export const ICON_REGISTRY_PROVIDER = {
260260
};
261261

262262
@NgModule({
263-
imports: [HttpModule, CompatibilityModule],
263+
imports: [HttpModule, CompatibilityModule, MdThemeCheckModule],
264264
exports: [MdIcon, CompatibilityModule],
265265
declarations: [MdIcon],
266266
providers: [ICON_REGISTRY_PROVIDER],

src/lib/input/index.ts

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
import {NgModule, ModuleWithProviders} from '@angular/core';
2-
import {MdPlaceholder, MdInputContainer, MdHint, MdInputDirective} from './input-container';
3-
import {MdTextareaAutosize} from './autosize';
42
import {CommonModule} from '@angular/common';
53
import {FormsModule} from '@angular/forms';
4+
import {MdThemeCheckModule} from '../core';
5+
import {MdPlaceholder, MdInputContainer, MdHint, MdInputDirective} from './input-container';
6+
import {MdTextareaAutosize} from './autosize';
67
import {PlatformModule} from '../core/platform/index';
78

89

@@ -23,6 +24,7 @@ export * from './input-container-errors';
2324
CommonModule,
2425
FormsModule,
2526
PlatformModule,
27+
MdThemeCheckModule,
2628
],
2729
exports: [
2830
MdPlaceholder,

src/lib/list/list.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,14 @@ import {
1111
NgModule,
1212
ModuleWithProviders,
1313
} from '@angular/core';
14-
import {MdLine, MdLineSetter, MdLineModule, CompatibilityModule} from '../core';
14+
import {
15+
MdLine,
16+
MdLineSetter,
17+
MdLineModule,
18+
CompatibilityModule,
19+
MdThemeCheckModule,
20+
} from '../core';
21+
1522

1623
@Directive({
1724
selector: 'md-divider, mat-divider'
@@ -72,7 +79,7 @@ export class MdListItem implements AfterContentInit {
7279

7380

7481
@NgModule({
75-
imports: [MdLineModule, CompatibilityModule],
82+
imports: [MdLineModule, CompatibilityModule, MdThemeCheckModule],
7683
exports: [
7784
MdList,
7885
MdListItem,

src/lib/menu/menu.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import {NgModule, ModuleWithProviders} from '@angular/core';
22
import {CommonModule} from '@angular/common';
3-
import {OverlayModule, CompatibilityModule} from '../core';
3+
import {OverlayModule, CompatibilityModule, MdThemeCheckModule} from '../core';
44
import {MdMenu} from './menu-directive';
55
import {MdMenuItem} from './menu-item';
66
import {MdMenuTrigger} from './menu-trigger';
@@ -13,7 +13,7 @@ export {MenuPositionX, MenuPositionY} from './menu-positions';
1313

1414

1515
@NgModule({
16-
imports: [OverlayModule, CommonModule, MdRippleModule, CompatibilityModule],
16+
imports: [OverlayModule, CommonModule, MdRippleModule, CompatibilityModule, MdThemeCheckModule],
1717
exports: [MdMenu, MdMenuItem, MdMenuTrigger, CompatibilityModule],
1818
declarations: [MdMenu, MdMenuItem, MdMenuTrigger],
1919
})

src/lib/module.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import {
99
A11yModule,
1010
ProjectionModule,
1111
CompatibilityModule,
12+
MdThemeCheckModule,
1213
} from './core/index';
1314

1415
import {MdButtonToggleModule} from './button-toggle/index';
@@ -61,6 +62,7 @@ const MATERIAL_MODULES = [
6162
MdTabsModule,
6263
MdToolbarModule,
6364
MdTooltipModule,
65+
MdThemeCheckModule,
6466
OverlayModule,
6567
PortalModule,
6668
RtlModule,

src/lib/progress-bar/progress-bar.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
Input,
88
} from '@angular/core';
99
import {CommonModule} from '@angular/common';
10-
import {CompatibilityModule} from '../core/compatibility/compatibility';
10+
import {CompatibilityModule, MdThemeCheckModule} from '../core';
1111

1212
// TODO(josephperrott): Benchpress tests.
1313
// TODO(josephperrott): Add ARIA attributes for progressbar "for".
@@ -86,7 +86,7 @@ function clamp(v: number, min = 0, max = 100) {
8686

8787

8888
@NgModule({
89-
imports: [CommonModule, CompatibilityModule],
89+
imports: [CommonModule, CompatibilityModule, MdThemeCheckModule],
9090
exports: [MdProgressBar, CompatibilityModule],
9191
declarations: [MdProgressBar],
9292
})

src/lib/progress-spinner/progress-spinner.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import {
1010
NgZone,
1111
Renderer
1212
} from '@angular/core';
13-
import {CompatibilityModule} from '../core';
13+
import {CompatibilityModule, MdThemeCheckModule} from '../core';
1414

1515

1616
// TODO(josephperrott): Benchpress tests.
@@ -362,7 +362,7 @@ function getSvgArc(currentValue: number, rotation: number) {
362362

363363

364364
@NgModule({
365-
imports: [CompatibilityModule],
365+
imports: [CompatibilityModule, MdThemeCheckModule],
366366
exports: [MdProgressSpinner, MdSpinner, CompatibilityModule],
367367
declarations: [MdProgressSpinner, MdSpinner],
368368
})

src/lib/radio/radio.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import {
2525
UniqueSelectionDispatcher,
2626
CompatibilityModule,
2727
UNIQUE_SELECTION_DISPATCHER_PROVIDER,
28+
MdThemeCheckModule,
2829
} from '../core';
2930
import {coerceBooleanProperty} from '../core/coercion/boolean-property';
3031
import {VIEWPORT_RULER_PROVIDER} from '../core/overlay/position/viewport-ruler';
@@ -507,7 +508,7 @@ export class MdRadioButton implements OnInit {
507508

508509

509510
@NgModule({
510-
imports: [CommonModule, MdRippleModule, CompatibilityModule],
511+
imports: [CommonModule, MdRippleModule, CompatibilityModule, MdThemeCheckModule],
511512
exports: [MdRadioGroup, MdRadioButton, CompatibilityModule],
512513
providers: [UNIQUE_SELECTION_DISPATCHER_PROVIDER, VIEWPORT_RULER_PROVIDER],
513514
declarations: [MdRadioGroup, MdRadioButton],

0 commit comments

Comments
 (0)