Angular Mat Datepicker-动态应用样式



我有一个Datepicker组件,它包含一个Material Datepicker。此组件接收一个datepickerConfig对象,该对象描述应如何设置日期选择器的样式。例如,这个对象描述了要应用的阴影级别、焦点样式、悬停样式等。

我对材质样式还很陌生,所以我想知道如何在运行时动态应用这些样式?

例如,对于阴影,我在SCSS文件中声明了以下变量:

/* shadow */
$shadow-opacity: rgba(0, 0, 0, 0.3);
$dp-box-shadow-mobile: 0 30px 40px $shadow-opacity;
$dp-box-shadow-desktop-1: 0 3px 6px $shadow-opacity;
$dp-box-shadow-desktop-2: 0 6px 12px $shadow-opacity;
...
// more variables for the different styles
.mat-datepicker-content {
// dynamically apply variables to these styles
// e.g. if datepickerConfig.shadow.level === 2 
// then $dp-box-shadow-desktop-2 should be applied 
box-shadow: ...; 
border: ...;
border-radius: ...;
...
}

在运行时,我需要检查datepickerConfig对象中的阴影级别,并将正确的样式动态应用于元素。

我的日期选择器模板:

<mat-form-field appearance="fill">
<mat-label>Choose a date</mat-label>
<input matInput [matDatepicker]="picker">    
<mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
<mat-datepicker #picker (opened)="opened()">
<mat-datepicker-actions>
<button mat-button matDatepickerCancel>CANCEL</button>
<button mat-raised-button matDatepickerApply>OK</button>
</mat-datepicker-actions>
</mat-datepicker>
</mat-form-field>

我如何实现这一点,不仅是对于阴影,而且对于我必须动态设置的多种样式?我想知道Angular有没有一种干净的方法。。。或者这只能针对带有JS的类来实现?

谢谢。

您可以通过使用CSS变量来实现您想要的。您不能使用SCSS变量,它们在运行时不可用,因为当SCSS编译为CSS时,它们就会消失。

现在对CSS变量的支持非常好。尽管IE11已退出游戏。

我在stackblitz中创建了一个示例,它使用CSS变量根据config提供的值动态更改按钮阴影的样式:https://stackblitz.com/edit/angular-ivy-cuyhed?file=src/app/fancy-button.com组件.ts

全局样式包含CSS变量的定义。

样式.css

:root {
/* shadow-opacity variables, that will be used based on the configuration */
--shadow-opacity-level-1: rgba(0, 0, 0, 1);
--shadow-opacity-level-2: rgba(0, 0, 0, 0.5);
/* default shadow opacity */
--shadow-opacity: var(--shadow-opacity-level-1);
}
/* global styles for a fancy-button, similar to your .mat-datepicker-content class */
.fancy-button {
border: 3px solid;
padding: 0.25em 0.5em;
/* here we use var(--shadow-opacity) to set default value, --shadow-opacity will be overridden later, based on the current configuration  */
box-shadow: 5px 5px 0px 0px var(--shadow-opacity);
}

接下来,我们需要一个按钮组件,它使用.fancy-button类,但也基于当前配置值覆盖--shadow-opacity变量的值。

getButtonStyle()方法检查config.shadowLevel值,并将--shadow-opacity变量设置为适当的阴影级别。

花式按钮组件.ts

@Component({
selector: 'fancy-button',
template: `
<button 
class="fancy-button"
style="{{getButtonStyle()}}"
>
{{config.label}}
</button>
`,
styles: [``]
})
export class FancyButtonComponent  {
@Input() config: FancyButtonConfig;
getButtonStyle(): string {
if (this.config.shadowLevel === 1) {
return '--shadow-opacity: var(--shadow-opacity-level-1)';
}
if (this.config.shadowLevel === 2) {
return '--shadow-opacity: var(--shadow-opacity-level-2)';
}
throw Error(`Unknown shadowLevel: ${this.config.shadowLevel}`);
}
}

包装

还可以选择使用自定义类和覆盖,正如Nathan在回答中所建议的那样。我认为CSS变量和类重写是相当等效的方法,当在这两者之间做出决定时,我会选择一种能够生成更干净、更易于维护的代码的方法。

资源

  • Kevin Powell对CSS变量的介绍
  • 覆盖";参数";CSS类的

用角材料组件扩展的答案

这个问题是专门问关于Angular材料组件的,但上面的答案描述了普通的HTML按钮。

我用FancyButtonMatWrapperComponent扩展了stackblitz演示,它封装了mat-raised-button,并根据提供的配置更改了其box-shadow

对于常规HTML按钮,所有的机制都是如上所述工作的。主要区别在于,index.html中的外部div具有类material-overrides,这有助于覆盖默认的"角度材质"样式。

全局styles.css然后包含以下覆盖

.material-overrides .mat-raised-button {
border: 3px solid black;
padding: 0.25em 0.5em;
box-shadow: 5px 5px 0px 0px var(--shadow-opacity);
}

您可以使用[ngStyle]指令——以这个基于条件动态设置宽度属性的示例为例。

<div [style.width.%]="condition ? 20 : 50" ...>

使用CCD_ 14或";"清洁剂";一旦您开始管理多个样式,上面的替代语法可能会变得混乱,并且不能真正用于获取模板中不可用的投影内容。

我可能建议使用类方法(带有[ngClass]属性指令(,并使用SCSS重写来有条件地重置某些属性。

<mat-form-field class="datepicker"
[class.datepicker--modified]="condition">
...
// in the SCSS
.datepicker {
color: red;
&--modified {
color: blue;
}
}

最新更新