Angular темизация через CSS переменные
В темизации всё более менее понятно, кроме момента как динамически менять значения цветов.
global style.scss
:root {
--background-color: lightyellow;
--text-color: darkslategray;
}
*.component.scss
:host {
display: block;
background-color: var(--background-color);
color: var(--text-color);
}
Чтобы поменять цвета необходимо заменить значение --background-color
и --text-color
. Однако через Renderer2 установить значения не предстваляется возможным.
constructor(
private _renderer: Renderer2,
private _el: ElementRef,
) {}
onChange(): void {
// затирает `--background-color: black;`
this._renderer.setProperty(this._el.nativeElement, 'style', '--background-color: black');
this._renderer.setProperty(this._el.nativeElement, 'style', '--text-color: red');
// затирает `--background-color: black;`
this._renderer.setAttribute(this._el.nativeElement, 'style', '--background-color: black');
this._renderer.setAttribute(this._el.nativeElement, 'style', '--text-color: red');
// вообще не работает т.к. не изменяет неизвестные свойства такие как CSS переменные
this._renderer.setStyle(this._el.nativeElement, '--background-color', 'black');
this._renderer.setStyle(this._el.nativeElement, '--text-color', 'red');
}
binding стилей напрямую также не работает
<hello name="{{ name }}" [ngStyle]="{'--text-color': 'green'}" [style.--text-color]="'blue'"></hello>
Для решения проблемы существует 2 подхода:
- Binding стилей через
DomSanitizer.bypassSecurityTrustStyle
- Манипуляция через
element.style.setProperty(cssVaribale, value);
nativeElement.style.setProperty
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
constructor(
private _elementRef: ElementRef
) {}
onChange(): void {
this._elementRef.nativeElement.style.setProperty('--background-color', 'black');
this._elementRef.nativeElement.style.setProperty('--text-color', 'red');
}
}
На счёт почему используется манипуляция со стилями напрямую this._elementRef.nativeElement.style.setProperty(…)
вместо Renderer2
Google Developr Expert ответил:
You no longer have to use renderer to do that in Angular6.
но не объяснил почему так.
DomSanitizer + HostBinding
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss'],
})
export class AppComponent {
private _style = '';
@HostBinding('style') get styleBinding(): SafeStyle {
return this._sanitizer.bypassSecurityTrustStyle(
this._style
);
}
constructor(
private _sanitizer: DomSanitizer
) {}
onChange(): void {
this._style = ['--background-color: black', '--text-color: red'].join(';');
}
}
Пример: