From acb5a6161ec403eca05c8c6d0e1d844a95afea84 Mon Sep 17 00:00:00 2001 From: DevVersion Date: Sun, 14 Feb 2016 11:45:45 +0100 Subject: [PATCH] fix(theming): theming should also watch for controller changes. As the dialog inherits the controllers not at link time, the theming won't work. Tried a few possibilities: - Walking through the DOM after show and re-theme the elements - Recompile the template after show But the most elegant and performant solution is definitely watching for the controller change. Fixes #5899 Closes #7154 --- src/core/services/theming/theming.js | 79 ++++++++++++++++------------ 1 file changed, 45 insertions(+), 34 deletions(-) diff --git a/src/core/services/theming/theming.js b/src/core/services/theming/theming.js index 25a7314d7eb..fc7d51112fd 100644 --- a/src/core/services/theming/theming.js +++ b/src/core/services/theming/theming.js @@ -334,27 +334,61 @@ function ThemingProvider($mdColorPalette) { */ /* @ngInject */ function ThemingService($rootScope, $log) { + // Allow us to be invoked via a linking function signature. + var applyTheme = function (scope, el) { + if (el === undefined) { el = scope; scope = undefined; } + if (scope === undefined) { scope = $rootScope; } + applyTheme.inherit(el, el); + }; - applyTheme.inherit = function(el, parent) { - var ctrl = parent.controller('mdTheme'); + applyTheme.THEMES = angular.extend({}, THEMES); + applyTheme.inherit = inheritTheme; + applyTheme.registered = registered; + applyTheme.defaultTheme = function() { return defaultTheme; }; + applyTheme.generateTheme = function(name) { generateTheme(name, nonce); }; + + return applyTheme; + /** + * Determine is specified theme name is a valid, registered theme + */ + function registered(themeName) { + if (themeName === undefined || themeName === '') return true; + return applyTheme.THEMES[themeName] !== undefined; + } + + /** + * Get theme name for the element, then update with Theme CSS class + */ + function inheritTheme (el, parent) { + var ctrl = parent.controller('mdTheme'); var attrThemeValue = el.attr('md-theme-watch'); - if ( (alwaysWatchTheme || angular.isDefined(attrThemeValue)) && attrThemeValue != 'false') { - var deregisterWatch = $rootScope.$watch(function() { - return ctrl && ctrl.$mdTheme || (defaultTheme == 'default' ? '' : defaultTheme); - }, changeTheme); - el.on('$destroy', deregisterWatch); - } else { - var theme = ctrl && ctrl.$mdTheme || (defaultTheme == 'default' ? '' : defaultTheme); - changeTheme(theme); + var watchTheme = (alwaysWatchTheme || angular.isDefined(attrThemeValue)) && attrThemeValue != 'false'; + + updateThemeClass(lookupThemeName()); + + el.on('$destroy', watchTheme ? $rootScope.$watch(lookupThemeName, updateThemeClass) : angular.noop ); + + /** + * Find the theme name from the parent controller or element data + */ + function lookupThemeName() { + // As a few components (dialog) add their controllers later, we should also watch for a controller init. + ctrl = parent.controller('mdTheme') || el.data('$mdThemeController'); + return ctrl && ctrl.$mdTheme || (defaultTheme == 'default' ? '' : defaultTheme); } - function changeTheme(theme) { + /** + * Remove old theme class and apply a new one + * NOTE: if not a valid theme name, then the current name is not changed + */ + function updateThemeClass(theme) { if (!theme) return; if (!registered(theme)) { $log.warn('Attempted to use unregistered theme \'' + theme + '\'. ' + 'Register it with $mdThemingProvider.theme().'); } + var oldTheme = el.data('$mdThemeName'); if (oldTheme) el.removeClass('md-' + oldTheme +'-theme'); el.addClass('md-' + theme + '-theme'); @@ -363,31 +397,8 @@ function ThemingProvider($mdColorPalette) { el.data('$mdThemeController', ctrl); } } - }; - - applyTheme.THEMES = angular.extend({}, THEMES); - applyTheme.defaultTheme = function() { return defaultTheme; }; - applyTheme.registered = registered; - applyTheme.generateTheme = function(name) { generateTheme(name, nonce); }; - - return applyTheme; - - function registered(themeName) { - if (themeName === undefined || themeName === '') return true; - return applyTheme.THEMES[themeName] !== undefined; } - function applyTheme(scope, el) { - // Allow us to be invoked via a linking function signature. - if (el === undefined) { - el = scope; - scope = undefined; - } - if (scope === undefined) { - scope = $rootScope; - } - applyTheme.inherit(el, el); - } } }