Dynamically loading a material theme in angular

前端 未结 6 1918
广开言路
广开言路 2020-12-10 07:55

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

相关标签:
6条回答
  • 2020-12-10 08:22
    <your_module>.config(function ($mdThemingProvider, $provide) {
         $provide.value('$mdThemingProvider', $mdThemingProvider);
    });
    

    Now you can inject $mdTheming and $mdThemingProvider in your controller and insert the code below in your controller.

    $mdThemingProvider.theme(<theme_name>).primaryPalette(<primary_color>).accentPalette(>accent_color>);
    $mdTheming.generateTheme(<theme_name>);
    

    If you want this to be your default theme, then:

    $mdThemingProvider.setDefaultTheme(<theme_name>);
    

    or use md-theme="<theme_name>" in HTML.

    PS: Works with Angular Material 1.1 and above.

    0 讨论(0)
  • 2020-12-10 08:28

    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);
    }
    
    0 讨论(0)
  • 2020-12-10 08:29

    I was also having a similar scenario, CSS has provided us a feature called var(), which allows us to runtime change properties of our CSS elements. Check my blog for more details here, hope this will help you

    0 讨论(0)
  • 2020-12-10 08:37

    This is easier now. You only have to omit the first step. In resume:

    1. Add reload: generateThemes in themingProvider function (angular-material.js)
    2. Make the provider available to your controllers:

      $provide.value('themeProvider', $mdThemingProvider);

    3. Create your theme in your controller using themeProvider

    4. Reload themes using themeProvider.reload($injector);
    0 讨论(0)
  • 2020-12-10 08:41

    The following worked for me, all credit to Guilhermecvm, however I'll add the code from the Github issue in case google brings anyone else here

    angular.module('app')
    .config(['$mdThemingProvider', '$provide', function($mdThemingProvider, $provide) {
        $mdThemingProvider.generateThemesOnDemand(true);
        $provide.value('themeProvider', $mdThemingProvider);
    }])
    
    .controller('AppController', ['themeProvider', '$mdTheming', function(themeProvider, $mdTheming) {
        //create new theme
        themeProvider.theme('default')
          .primaryPalette('pink')
          .accentPalette('orange')
          .backgroundPalette('yellow');
    
        //reload the theme
        $mdTheming.generateTheme('default');
    
        //optional - set the default to this new theme
        themeProvider.setDefaultTheme('default');
    }]);
    

    To avoid 'attempted to use unregistered theme' warnings, the theme should be added to the mdTheming internal list of themes

    var theme = themeProvider.theme...
    $mdTheming.THEMES[themeName] = theme;
    
    0 讨论(0)
  • 2020-12-10 08:45

    As of version 1.0.5 of angular-material:

    1. 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)

    2. In config function:

      angular.module('my-module').config(function ($provide, $mdThemingProvider) {
       $mdThemingProvider.generateThemesOnDemand(true);
       $provide.value('themeProvider', $mdThemingProvider);});
      
    3. 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');
      
    0 讨论(0)
提交回复
热议问题