Angular - 如何使用 mixin 为我自己的组件设置主题?
Angular - how to theme my own component using mixin?
我创建了一个组件:
message.component.html
<div class="alert">
<div class="row">
<!-- add no-gutters to make it narrower -->
<div class="col-auto align-self-start">
<!-- or align-self-center -->
<mat-icon>{{icon}}</mat-icon>
</div>
<div class="col">
<div class="app-message-title">{{title}}</div>
<div class="app-message-content">
<ng-content></ng-content>
</div>
</div>
</div>
</div>
message.component.ts
import { Component, OnInit, Input, ElementRef } from '@angular/core';
import { CanColorCtor, mixinColor, CanColor, ThemePalette } from '@angular/material';
// Boilerplate for applying mixins to MessageComponent.
/** @docs-private */
class MessageComponentBase {
constructor(public _elementRef: ElementRef) { }
}
const _MessageComponentMixinBase: CanColorCtor & typeof MessageComponentBase = mixinColor(MessageComponentBase);
@Component({
selector: 'app-message',
templateUrl: './message.component.html',
styleUrls: ['./message.component.scss']
})
export class MessageComponent extends _MessageComponentMixinBase implements CanColor, OnInit {
@Input() title: string;
@Input() icon: string;
@Input() color: ThemePalette;
constructor(
elementRef: ElementRef) {
super(elementRef);
}
ngOnInit() {
}
}
message.component.css
@mixin app-message-typography($config) {
.app-message-title {
font: {
family: app-font-family($config);
size: app-font-size($config, body-2);
weight: 600;
}
line-height: app-line-height($config, body-2);
}
.app-message-content {
font: {
family: app-font-family($config);
size: app-font-size($config, body-1);
}
}
}
@mixin app-message($theme) {
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
.app-message {
&.mat-primary {
color: mat-color($primary);
background-color: mat-color($primary, 0.15);
}
&.mat-accent {
color: mat-color($accent);
background-color: mat-color($accent, 0.15);
}
&.mat-warn {
color: mat-color($warn);
background-color: mat-color($warn, 0.15);
}
}
}
显示-message.component.html
<app-message title="Login failed"
color="warn"
icon="warning"
>Test</app-message>
代码编译正确,我可以看到生成的 html 是正确的:
<app-message _ngcontent-gus-c16="" class="ng-tns-c16-3 mat-warn" color="warn" icon="warning" title="Login failed" _nghost-gus-c20="" ng-reflect-title="Login failed" ng-reflect-icon="warning" ng-reflect-color="warn">
<div _ngcontent-gus-c20="" class="alert">
<div _ngcontent-gus-c20="" class="row">
<div _ngcontent-gus-c20="" class="col-auto align-self-start">
<mat-icon _ngcontent-gus-c20="" class="mat-icon notranslate material-icons mat-icon-no-color" role="img" aria-hidden="true">warning</mat-icon>
</div>
<div _ngcontent-gus-c20="" class="col">
<div _ngcontent-gus-c20="" class="app-message-title">Login failed</div>
<div _ngcontent-gus-c20="" class="app-message-content">Test</div>
</div>
</div>
</div>
但是样式应用不正确,背景和文本应该是橙色(警告色)。
如何使用 mixin 在我的组件上应用样式?
谢谢
编辑:
根据@Jorge Mussato 的建议,我做了一些调整:
themes.scss:
@import './message/message.component.scss';
// Create a theme.
@mixin themes($theme, $config: null) {
//@include app-message-typography($config); //Not necessary for the moment
@include app-message-theme($theme);
}
styles.scss
[...]
@import 'src/app/components/themes.scss';
[...]
$primary: ...;
$accent: ..;
$warn: ...;
$theme: mat-light-theme($primary, $accent, $warn);
[...]
@include themes($theme, $typography);
为了确保错误不是来自我的 scss,我将 messsage.component.ts 更新为:
@mixin app-message-theme($theme) {
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
// I added this :
:host {
display: block;
background-color: green;
}
[...]
}
}
代码编译正确,但我仍然继续在我的组件上应用主题。
您需要在 styles.scss(或主主题文件)
中声明您的 mixin
styles.scss
...
$config: ...;
$theme: ...;
@import 'path-to-file/message.component.scss';
@include app-message-typography($config);
@include app-message($theme);
...
我找到了解决方案,感谢@Jorge Mussato 的帮助!
在 message.component.scss 中,好的做法是(我用 app-message 替换了 .app-message 并添加了 .alert):
@mixin app-message-theme($theme) {
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
app-message {
&.mat-primary .alert {
color: mat-color($primary);
background-color: mat-color($primary, 0.15);
}
&.mat-accent .alert {
color: mat-color($accent);
background-color: mat-color($accent, 0.15);
}
&.mat-warn .alert {
color: mat-color($warn);
background-color: mat-color($warn, 0.15);
}
}
}
这是提交差异:
https://github.com/ranouf/AllInOneV2/commit/115194b8ca8d098718efa855275e203ba6d276ac
我创建了一个组件:
message.component.html
<div class="alert">
<div class="row">
<!-- add no-gutters to make it narrower -->
<div class="col-auto align-self-start">
<!-- or align-self-center -->
<mat-icon>{{icon}}</mat-icon>
</div>
<div class="col">
<div class="app-message-title">{{title}}</div>
<div class="app-message-content">
<ng-content></ng-content>
</div>
</div>
</div>
</div>
message.component.ts
import { Component, OnInit, Input, ElementRef } from '@angular/core';
import { CanColorCtor, mixinColor, CanColor, ThemePalette } from '@angular/material';
// Boilerplate for applying mixins to MessageComponent.
/** @docs-private */
class MessageComponentBase {
constructor(public _elementRef: ElementRef) { }
}
const _MessageComponentMixinBase: CanColorCtor & typeof MessageComponentBase = mixinColor(MessageComponentBase);
@Component({
selector: 'app-message',
templateUrl: './message.component.html',
styleUrls: ['./message.component.scss']
})
export class MessageComponent extends _MessageComponentMixinBase implements CanColor, OnInit {
@Input() title: string;
@Input() icon: string;
@Input() color: ThemePalette;
constructor(
elementRef: ElementRef) {
super(elementRef);
}
ngOnInit() {
}
}
message.component.css
@mixin app-message-typography($config) {
.app-message-title {
font: {
family: app-font-family($config);
size: app-font-size($config, body-2);
weight: 600;
}
line-height: app-line-height($config, body-2);
}
.app-message-content {
font: {
family: app-font-family($config);
size: app-font-size($config, body-1);
}
}
}
@mixin app-message($theme) {
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
.app-message {
&.mat-primary {
color: mat-color($primary);
background-color: mat-color($primary, 0.15);
}
&.mat-accent {
color: mat-color($accent);
background-color: mat-color($accent, 0.15);
}
&.mat-warn {
color: mat-color($warn);
background-color: mat-color($warn, 0.15);
}
}
}
显示-message.component.html
<app-message title="Login failed"
color="warn"
icon="warning"
>Test</app-message>
代码编译正确,我可以看到生成的 html 是正确的:
<app-message _ngcontent-gus-c16="" class="ng-tns-c16-3 mat-warn" color="warn" icon="warning" title="Login failed" _nghost-gus-c20="" ng-reflect-title="Login failed" ng-reflect-icon="warning" ng-reflect-color="warn">
<div _ngcontent-gus-c20="" class="alert">
<div _ngcontent-gus-c20="" class="row">
<div _ngcontent-gus-c20="" class="col-auto align-self-start">
<mat-icon _ngcontent-gus-c20="" class="mat-icon notranslate material-icons mat-icon-no-color" role="img" aria-hidden="true">warning</mat-icon>
</div>
<div _ngcontent-gus-c20="" class="col">
<div _ngcontent-gus-c20="" class="app-message-title">Login failed</div>
<div _ngcontent-gus-c20="" class="app-message-content">Test</div>
</div>
</div>
</div>
但是样式应用不正确,背景和文本应该是橙色(警告色)。
如何使用 mixin 在我的组件上应用样式?
谢谢
编辑:
根据@Jorge Mussato 的建议,我做了一些调整:
themes.scss:
@import './message/message.component.scss';
// Create a theme.
@mixin themes($theme, $config: null) {
//@include app-message-typography($config); //Not necessary for the moment
@include app-message-theme($theme);
}
styles.scss
[...]
@import 'src/app/components/themes.scss';
[...]
$primary: ...;
$accent: ..;
$warn: ...;
$theme: mat-light-theme($primary, $accent, $warn);
[...]
@include themes($theme, $typography);
为了确保错误不是来自我的 scss,我将 messsage.component.ts 更新为:
@mixin app-message-theme($theme) {
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
// I added this :
:host {
display: block;
background-color: green;
}
[...]
}
}
代码编译正确,但我仍然继续在我的组件上应用主题。
您需要在 styles.scss(或主主题文件)
中声明您的 mixinstyles.scss
...
$config: ...;
$theme: ...;
@import 'path-to-file/message.component.scss';
@include app-message-typography($config);
@include app-message($theme);
...
我找到了解决方案,感谢@Jorge Mussato 的帮助!
在 message.component.scss 中,好的做法是(我用 app-message 替换了 .app-message 并添加了 .alert):
@mixin app-message-theme($theme) {
$primary: map-get($theme, primary);
$accent: map-get($theme, accent);
$warn: map-get($theme, warn);
app-message {
&.mat-primary .alert {
color: mat-color($primary);
background-color: mat-color($primary, 0.15);
}
&.mat-accent .alert {
color: mat-color($accent);
background-color: mat-color($accent, 0.15);
}
&.mat-warn .alert {
color: mat-color($warn);
background-color: mat-color($warn, 0.15);
}
}
}
这是提交差异: https://github.com/ranouf/AllInOneV2/commit/115194b8ca8d098718efa855275e203ba6d276ac