We can create an attribute directive which accepts the color value and override default styles of <mat-progress-bar>
for us.
here is a working demo : https://stackblitz.com/edit/material-progress-bar-color-directive
here is a brief explanation:
If we inspect <mat-progress-bar>
in developer tools. we will find that color of the progress-bar is defined in the ::after
pseudo element like this.
.mat-progress-bar-fill::after {
background-color: #3f51b5;
}
And as we already know that it is not possible to directly manipulate a pseudo element using DOM querySelector() method. But we can add new styles which can have rules for pseudo elements too. checkout this thread for more details. https://stackoverflow.com/a/21709814/1160236
So, we can make a directive which can take care of adding new styles for us.
import { Directive, Input, OnChanges, SimpleChanges, ElementRef } from '@angular/core';
@Directive({
selector: '[appProgressBarColor]'
})
export class ProgressBarColor implements OnChanges{
static counter = 0;
@Input() appProgressBarColor;
styleEl:HTMLStyleElement = document.createElement('style');
//generate unique attribule which we will use to minimise the scope of our dynamic style
uniqueAttr = `app-progress-bar-color-${ProgressBarColor.counter++}`;
constructor(private el: ElementRef) {
const nativeEl: HTMLElement = this.el.nativeElement;
nativeEl.setAttribute(this.uniqueAttr,'');
nativeEl.appendChild(this.styleEl);
}
ngOnChanges(changes: SimpleChanges): void{
this.updateColor();
}
updateColor(): void{
// update dynamic style with the uniqueAttr
this.styleEl.innerText = `
[${this.uniqueAttr}] .mat-progress-bar-fill::after {
background-color: ${this.appProgressBarColor};
}
`;
}
}
as you can see that all that we are doing here is just making a new HtmlStyleElement
and adding it just inside the host element.
And inside updateColor()
method we are updating the innerText
of the style tag we have appended. notice that we are using an attribute selector here with a unique attribute to minimize the scope of the style to the host only. because we want to override the style only for that progress-bar on which we have applied our directive.
you can use this directive in your template like this.
<mat-progress-bar [appProgressBarColor]="'orange'"
mode="determinate"
value="40"></mat-progress-bar>
I hope this will help.