Search code examples
angularangular-directive

How to Change color of all components with a given directive when the user chooses a different theme?


I am building an online document builder using angular 4. I have directives like my-header, my-subheader which will be applied to the angular components and they control the CSS property of the component like bold, font size, etc.

I would like to change the color of the components when the user chooses a different theme for all the components that have "my-header" directive from red to blue.

I don't know how this is possible in Angular 4.

 @Directive({
  selector: '[my-header]'
 })
 export class MyHeaderDirective {

    constructor(renderer: Renderer2, hostElement: ElementRef) {

            renderer.addClass(hostElement.nativeElement, 'header-class');

    }
}

And the html looks like this.

<app-element my-header></app-element>

When a user clicks on the button to change theme, I need to change the background color that I apply using the header-class. Or if I can apply the CSS using a different class is also fine. But, the change triggered from outside of any of these elements, needs to be injected into all these elements with the specific directive.

Any help would be much appreciated.


Solution

  • I'd recommend to create a service, for instance called ThemeService, to hold the currently active theme. You can then inject that service whereever needed to set or get the active theme (in your case in the my-header directive and the component you use to select a theme). I created a little example on StackBlitz to demonstrate how to do it: https://stackblitz.com/edit/angular-w98pvx

    The relevant classes are theme.service.ts

    @Injectable({
      providedIn: 'root'
    })
    export class ThemeService {
      currentThemeSubject: BehaviorSubject<Theme> = new BehaviorSubject<Theme>(themes[0])
    
      get theme() {
        return this.currentThemeSubject.value;
      }
    
      set theme(theme: Theme) {
        this.currentThemeSubject.next(theme);
      }
    }
    

    and my-header.directive.ts

    export class MyHeaderDirective {
    
       @HostBinding('style.backgroundColor') get color() {
         return this.themeService.theme.backgroundColor;
       };
    
        constructor(renderer: Renderer2, hostElement: ElementRef, private themeService: ThemeService) {
          renderer.addClass(hostElement.nativeElement, 'header-class');
        }
    }