I'm building an Angular application using Angular Material. One of the first steps in the application is that the user logs in. Next, the system loads from the backend the theme made by that user's company.
However, when the backend responds with the Theme information, I am not able to get it into the system. The $mdThemingProvider, which allows you to set themes, does not seem to be available from inside a Controller and the $mdTheming service itself does not have options for modifying the themes in the system.
Is there any way to dynamically load new themes into an Angular Material application?
As of version 1.0.5 of angular-material:
Add
reload: generateTheme
in themingProvider function (angular-material.js line 4840 - the generateTheme function is already present in angular-material.js, we just need a way to call it)
In config function:
angular.module('my-module').config(function ($provide, $mdThemingProvider) {
$mdThemingProvider.generateThemesOnDemand(true);
$provide.value('themeProvider', $mdThemingProvider);});
In your controller, inject themeProvider and now you can do something like:
//create new theme
themeProvider.theme('custom')
.primaryPalette('pink')
.accentPalette('orange')
.backgroundPalette('yellow');
//reload the theme
themeProvider.reload('custom');
//optional - set the default to this new theme
themeProvider.setDefaultTheme('custom');
I have managed to fix this by making some minor changes to the provider. To allow themes to be changed:
First, modify the generateThemes function in angular-material.js to set generationIsDone = false.
This will allow you to regenerate the themes at a later time.
function generateThemes($injector) {
var styles = $injector.has('$MD_THEME_STYLESHEETS') ? $injector.get('$MD_THEME_STYLESHEETS') : [];
if (styles) {
var $q = $injector.get('$q');
var $http = $injector.get('$http');
var calls = [];
angular.forEach(styles, function(style){
calls.push($http.get(style));
});
$q.all(calls).then(function(responses) {
var css = '';
angular.forEach(responses, function(response) {
css += response.data;
});
generationIsDone = false; // here
generateCss(css);
});
} else {
var css = $injector.has('$MD_THEME_CSS') ? $injector.get('$MD_THEME_CSS') : '';
generationIsDone = false; // here
generateCss(css);
}
}
Second, make the generateThemes() function available as a property on the ThemingService.
You can call it when you have added new themes, to generate their CSS.
ThemingService.$inject = ["$rootScope"];
return themingProvider = {
definePalette: definePalette,
extendPalette: extendPalette,
theme: registerTheme,
setDefaultTheme: function(theme) {
defaultTheme = theme;
},
alwaysWatchTheme: function(alwaysWatch) {
alwaysWatchTheme = alwaysWatch;
},
reload: generateThemes, // here
$get: ThemingService,
_LIGHT_DEFAULT_HUES: LIGHT_DEFAULT_HUES,
_DARK_DEFAULT_HUES: DARK_DEFAULT_HUES,
_PALETTES: PALETTES,
_THEMES: THEMES,
_parseRules: parseRules,
_rgba: rgba
};
Third, to actually make the ThemingProvider available to your controllers, add it to your module as a value.
angular.module("yourModule",['whateverDependencies']) .config(function($provide, $mdThemingProvider) { $provide.value('themeProvider', $mdThemingProvider); // now you can inject the provider })
And finally, where you need it, just call for the value in your controllers:
}).controller('someController', function(themeProvider, $injector) {
themeProvider.theme('someNewTheme').primaryColor('orange').accentColor('pink');
themeProvider.reload($injector);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With