Skip to content
This repository was archived by the owner on Sep 5, 2024. It is now read-only.

Commit 9310a84

Browse files
committed
feat(themes): register theme on the fly
- By using `defineTheme` of `$mdTheming` you can specify the name of the theme and the palettes, combined with `md-deferred-theme` directive to avoid warnings on not defined themes fixes #2965
1 parent 0cd2a59 commit 9310a84

File tree

2 files changed

+83
-6
lines changed

2 files changed

+83
-6
lines changed

src/core/services/theming/theming.js

Lines changed: 40 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
*/
99
angular.module('material.core.theming', ['material.core.theming.palette', 'material.core.meta'])
1010
.directive('mdTheme', ThemingDirective)
11+
.directive('mdDeferredTheme', ThemingDirective)
1112
.directive('mdThemable', ThemableDirective)
1213
.directive('mdThemesDisabled', disableThemesDirective )
1314
.provider('$mdTheming', ThemingProvider)
@@ -546,12 +547,42 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
546547
applyTheme.inherit(el, el);
547548
};
548549

549-
applyTheme.THEMES = angular.extend({}, THEMES);
550-
applyTheme.PALETTES = angular.extend({}, PALETTES);
550+
Object.defineProperty(applyTheme, 'THEMES', {
551+
get: function () {
552+
return angular.extend({}, THEMES);
553+
}
554+
});
555+
Object.defineProperty(applyTheme, 'PALETTES', {
556+
get: function () {
557+
return angular.extend({}, PALETTES);
558+
}
559+
});
551560
applyTheme.inherit = inheritTheme;
552561
applyTheme.registered = registered;
553562
applyTheme.defaultTheme = function() { return defaultTheme; };
554563
applyTheme.generateTheme = function(name) { generateTheme(THEMES[name], name, themeConfig.nonce); };
564+
applyTheme.defineTheme = function (name, options) {
565+
options = options || {};
566+
567+
var theme = registerTheme(name);
568+
569+
if (options.primary) {
570+
theme.primaryPalette(options.primary);
571+
}
572+
if (options.accent) {
573+
theme.accentPalette(options.accent);
574+
}
575+
if (options.warn) {
576+
theme.warnPalette(options.warn);
577+
}
578+
if (options.background) {
579+
theme.backgroundPalette(options.background);
580+
}
581+
582+
this.generateTheme(name);
583+
584+
return theme;
585+
};
555586
applyTheme.setBrowserColor = enableBrowserColor;
556587

557588
return applyTheme;
@@ -593,7 +624,7 @@ function ThemingProvider($mdColorPalette, $$mdMetaProvider) {
593624
*/
594625
function updateThemeClass(theme) {
595626
if (!theme) return;
596-
if (!registered(theme)) {
627+
if (ctrl && !ctrl.$isDeferredTheme && !registered(theme)) {
597628
$log.warn('Attempted to use unregistered theme \'' + theme + '\'. ' +
598629
'Register it with $mdThemingProvider.theme().');
599630
}
@@ -628,6 +659,7 @@ function ThemingDirective($mdTheming, $interpolate, $log) {
628659
priority: 100,
629660
link: {
630661
pre: function(scope, el, attrs) {
662+
var isDeferred = attrs.hasOwnProperty('mdDeferredTheme');
631663
var registeredCallbacks = [];
632664
var ctrl = {
633665
registerChanges: function (cb, context) {
@@ -646,19 +678,21 @@ function ThemingDirective($mdTheming, $interpolate, $log) {
646678
};
647679
},
648680
$setTheme: function (theme) {
649-
if (!$mdTheming.registered(theme)) {
681+
if (!isDeferred && !$mdTheming.registered(theme)) {
650682
$log.warn('attempted to use unregistered theme \'' + theme + '\'');
651683
}
652684
ctrl.$mdTheme = theme;
685+
ctrl.$isDeferredTheme = isDeferred;
653686

654687
registeredCallbacks.forEach(function (cb) {
655688
cb();
656689
});
657690
}
658691
};
659692
el.data('$mdThemeController', ctrl);
660-
ctrl.$setTheme($interpolate(attrs.mdTheme)(scope));
661-
attrs.$observe('mdTheme', ctrl.$setTheme);
693+
var directiveType = isDeferred ? 'mdDeferredTheme' : 'mdTheme';
694+
ctrl.$setTheme($interpolate(attrs[directiveType])(scope));
695+
attrs.$observe(directiveType, ctrl.$setTheme);
662696
}
663697
}
664698
};

src/core/services/theming/theming.spec.js

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -737,6 +737,17 @@ describe('$mdTheming service', function() {
737737
expect($mdTheming.defaultTheme()).toBe('default');
738738
}));
739739

740+
it('supports registering theme on the fly', inject(function ($mdTheming) {
741+
expect($mdTheming.THEMES.hasOwnProperty('test')).toBeFalsy();
742+
743+
$mdTheming.defineTheme('test', {
744+
primary: 'red',
745+
warn: 'yellow'
746+
});
747+
748+
expect($mdTheming.THEMES.hasOwnProperty('test')).toBeTruthy();
749+
}));
750+
740751
it('supports changing browser color on the fly', function() {
741752
var name = 'theme-color';
742753
var primaryPalette = $mdThemingProvider._THEMES.default.colors.primary.name;
@@ -787,6 +798,38 @@ describe('md-theme directive', function() {
787798
});
788799
});
789800

801+
describe('md-deferred-theme directive', function() {
802+
beforeEach(module('material.core'));
803+
804+
it('should observe and set mdTheme controller', inject(function($compile, $rootScope) {
805+
$rootScope.themey = 'unregistered';
806+
var el = $compile('<div md-deferred-theme="{{themey}}">')($rootScope);
807+
$rootScope.$apply();
808+
var ctrl = el.data('$mdThemeController');
809+
expect(ctrl.$mdTheme).toBe('unregistered');
810+
$rootScope.$apply('themey = "blue"');
811+
expect(ctrl.$mdTheme).toBe('blue');
812+
}));
813+
814+
it('does not warns when an unregistered theme is used', function() {
815+
inject(function($log, $compile, $rootScope) {
816+
spyOn($log, 'warn');
817+
$compile('<div md-deferred-theme="unregistered"></div>')($rootScope);
818+
$rootScope.$apply();
819+
expect($log.warn).not.toHaveBeenCalled();
820+
});
821+
});
822+
823+
it('does not warn when a registered theme is used', function() {
824+
inject(function($log, $compile, $rootScope) {
825+
spyOn($log, 'warn');
826+
$compile('<div md-deferred-theme="default"></div>')($rootScope);
827+
$rootScope.$apply();
828+
expect($log.warn.calls.count()).toBe(0);
829+
});
830+
});
831+
});
832+
790833
describe('md-themable directive', function() {
791834
var $mdThemingProvider;
792835
beforeEach(module('material.core', function(_$mdThemingProvider_) {

0 commit comments

Comments
 (0)