1

For a project I have used the mat-slide-toggle of the Materials library. Now I want to change the color of the slider and the circle, which are the classes mat-slide-toggle-bar and mat-slide-toggle-thumb. I can set the background-color of both via the css-file, but here's the catch. I have several slide-toggles which all need different colors. The colors are defined in a dataset available in the component. I can access this dataset in the html, but not in the css. I can't use style="background-color: ..." on the mat-slide-toggle because it is not on the right class. The two classes I need are not directly visible in the html.

Html looks like this:

<span *ngFor="let data of dataSets">
<mat-slide-toggle (change)="toggleDataSet($event)">{{data.label}}</mat-slide-toggle>
</span>

So I need to either access the dataset in the css or somehow be able to set the background-color on nested classes not visible in the html. Is there a way to do this?

1 Answer 1

5

For changing the color of the sliders dynamically, you can create a Directive that receives the color for the circle and the one for the slider as inputs. The directive add attributes on the element and adds the styling needed to change the colors:

There is a similar answer given for changing the color for a progress bar here: Change angular material progress bar color from code.

The directive you need looks like this:

@Directive({
  selector: '[sliderColor]'
})
export class SliderColorDirective implements OnChanges {
  static sliderNumberCounter = 0;

  @Input() circleColor: number;
  @Input() sliderColor: number;
  styleElement: HTMLStyleElement = document.createElement('style');

  attributeName: string;

  constructor(private el: ElementRef) {
    this.attributeName = `slider-color-${SliderColorDirective.sliderNumberCounter}`;
    SliderColorDirective.sliderNumberCounter++;
    const nativeEl: HTMLElement = this.el.nativeElement;
    nativeEl.setAttribute(this.attributeName, '');
    nativeEl.appendChild(this.styleElement);
  }

  ngOnChanges(): void {
    this.setColors();
  }

  setColors(): void {
    this.styleElement.innerText = `
      [${this.attributeName}] .mat-slide-toggle-bar {
        background-color: ${this.sliderColor};
      }
      [${this.attributeName}] .mat-slide-toggle-thumb {
        background-color: ${this.circleColor};
      }
    `;
  }
}

The directive can be used like this:

<mat-slide-toggle sliderColor [sliderColor]="'red'" [circleColor]="'black'">{{data.label}}</mat-slide-toggle>
Sign up to request clarification or add additional context in comments.

5 Comments

Awesome! I will try it out as soon as I'm able and let you know if it works and then accept your answer.
I was able to implement it and it worked perfectly. The only change I would suggest is to add .mat-checked directly following the attributeName. If you don't, you get the default colours on the checked-version and your own colours on the unchecked one, while I wanted the checked-version to have my colours and I'm fine with the default grey for unchecked.
To make this work on IE, you should avoid the line breaks.
This doesn't seem to work for me.. I always get Can't bind to 'sliderColor' since it isn't a known property of 'mat-slide-toggle'. Any idea why?
@thomas Did you add the directive to the declarations in the module you want to use it? Or if it is used in multiple modules from the application, you should create a shared module and declare and export the directive from there and add the shared module to the imports from you module

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.