英文:
Angular v13: Separate Styles and Theme for 2 different parts of an Angular / Material Application
问题
我正在创建一个包含三个不同部分的Angular应用程序,这三个部分可以由三种不同类型的用户访问:管理员、土地所有者和买家。买家部分是一个新的部分,我需要为这部分创建新的主题/样式。有特定于组件的.scss文件,以及包含在_global.scss
文件和_layout.scss
文件中的全局样式。还有一个styles.scss
文件,它在angular.json
文件的styles
部分声明,并且injection
设置为true
。我只希望全局样式(_global
和_layout
)对应用程序的管理员和土地所有者组件可见,而不对买家组件可见。管理员还可以访问所有路由,因此他们可以随意导航到任何地方。我的app-routing.module
路由模块大致如下:
app.component
- ''路径重定向到login.component
- login.component
- admin-dashboard.component
- 具有子路由的router-outlet
- admin-project.component
- 具有子路由的router-outlet
- landowner-dashboard.component
- 具有子路由的router-outlet
- 买家.dashboard.component
- 具有子路由的router-outlet
到目前为止,我已尝试将顶级组件(如login.component
、admin-dashboard.component
等)在此路由模块中切换ViewEncapsulation
为None
,然后将_global.scss
和_layout.scss
导入到这些顶级组件中。这在管理员开始在各个部分之间导航时有效,管理员部分的样式开始覆盖买家部分的样式。我尝试编辑angular.json
以将全局样式表的inject
设置为false
,然后为所有顶级组件导入这些样式表,但出现了相同的问题。我尝试将全局样式包装在一个类中,然后将所有管理员和土地所有者组件的容器设置为具有这个类,但样式未被应用。我还遵循了Angular创建多个主题的指南,但样式未被应用(这里贴太多代码了)。有人遇到过这种问题并知道如何在高层次上使其工作吗?
英文:
I am creating an angular application with 3 different parts which are accessible by 3 different types of users: admin, landowner, and buyer. The buyer section is a new section and I need to create a new theme / styles for this section. There are component specific .scss files as well as global styles which are contained in a _global.scss
file and a _layout.scss
file. There is also a styles.scss
file which is declared in the styles
section of the angular.json
file with injection set to true
. I only want the global styles (_global
and _layout
) to be accessible to admin and landowner components of the application, and not the buyer components. The admin can also access all routes, so they will be able to navigate anywhere they like. My app-routing.module
routing module looks something like this:
app.component
- '' path redirects to login.component
- login.component
- admin-dashboard.component
- router-outlet with subroutes
- admin-project.component
- router-outlet with subroutes
- landowner-dashboard.component
- router-outlet with subroutes
- buyer.dashboard.component
- router-outlet with subroutes
So far I have tried switching the ViewEncapsulation
to None
for the top level components being mounted above (i.e. login.component
, admin-dashboard.component
, etc) in this routing module, and then importing the _global.scss
and _layout.scss
into each of those top level components. That works until an admin starts navigating in between sections and the styles from the admin section start to override the styles from the buyer section. I have tried to edit the angular.json
to set inject: false
for the global style sheets mentioned, and then importing those stylesheets for all the top level components, with the same issue. I have tried wrapping the global styles in a class, and then setting the containers for all the admin and landowner components to have this class, and the styles were not being applied. I have also followed the angular guides for creating multiple themes, and the styles were not being applied (there would also be too much code to paste here). Has anyone run into this type of problem and know how to get it to work at a high level?
答案1
得分: 1
以下是翻译好的部分:
在我的路由中,我向路由数据添加一个名为“theme”的字段,类似于:
{
path: 'admin',
component: AdminComponent,
data: {
theme: 'admin'
}
}
在app.component.ts中,我订阅路由更改事件,并在应用程序的body标签上设置一个类,用于表示我的主题值:
this.router.events.pipe(filter((event) => event instanceof NavigationEnd))
.subscribe(() => {
this.elementRef.nativeElement.ownerDocument.body.className = route.snapshot.data['theme'];
});
最后,在我的顶级样式中,我可以应用样式和嵌套在这些主题类中的主题,这些样式将覆盖基本主题:
$primary: mat-palette($mat-blue, 500, 300, 700);
$accent: mat-palette($mat-gray, 200);
$warn: mat-palette($mat-red, A700, 50);
$theme: mat-light-theme($primary, $accent, $warn);
@include angular-material-theme($theme);
// 附加的默认/基本样式
.admin {
$admin-primary: mat-palette($mat-green, 500, 300, 700);
$admin-theme: mat-light-theme($admin-primary, $accent, $warn);
@include angular-material-theme($admin-theme);
// 附加的自定义样式
}
英文:
I currently do the following for theme swapping and this may be helpful for your situation:
In my routes, I add a 'theme' field to the route data, something like:
{
path: 'admin',
component: AdminComponent,
data: {
theme: 'admin'
}
}
In app.component.ts I subscribe to router changes, and the set a class on the applications body tag for my theme value
this.router.events.pipe(filter((event) => event instanceof NavigationEnd))
.subscribe(() => {
this.elementRef.nativeElement.ownerDocument.body.className = route.snapshot.data['theme'];
});
Lastly, in my top level style I can apply style and themes nested in these theme classes that will override the base theme
$primary: mat-palette($mat-blue, 500, 300, 700);
$accent: mat-palette($mat-gray, 200);
$warn: mat-palette($mat-red, A700, 50);
$theme: mat-light-theme($primary, $accent, $warn);
@include angular-material-theme($theme);
// additional default/base style
.admin {
$admin-primary: mat-palette($mat-green, 500, 300, 700);
$admin-theme: mat-light-theme($admin-primary, $accent, $warn);
@include angular-material-theme($admin-theme);
// Additional custom style
}
答案2
得分: 1
I got it working using @robbieAreBests answer and without setting ViewEncapsulation to None. I had to alter the router subscription in the app.component slightly because I am trying to get the data object from a child route within a <router-outlet>
constructor(
private router: Router,
private route: ActivatedRoute,
private elementRef: ElementRef
){
this.router.events.subscribe((data) => {
if (data instanceof RoutesRecognized) {
this.elementRef.nativeElement.ownerDocument.body.className = data.state.root.firstChild.data['theme'];
}
});
}
英文:
I got it working using @robbieAreBests answer and without setting ViewEncapsulation to None. I had to alter the router subscription in the app.component slightly because I am trying to get the data object from a child route within a <router-outlet>
constructor(
private router: Router,
private route: ActivatedRoute,
private elementRef: ElementRef
){
this.router.events.subscribe((data) => {
if (data instanceof RoutesRecognized) {
this.elementRef.nativeElement.ownerDocument.body.className = data.state.root.firstChild.data['theme'];
}
});
}
答案3
得分: 0
抱歉,代码部分无法提供翻译。以下是您要翻译的内容:
"I think what you are looking for are module scoped style, unfortunately this is not a feature currently available.
英文:
I think what you are looking for are module scoped style, unfortunately this is not a feature currently available.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论