Angular v13:将Angular / Material应用程序的两个不同部分的样式和主题分开。

huangapple go评论60阅读模式
英文:

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.componentadmin-dashboard.component等)在此路由模块中切换ViewEncapsulationNone,然后将_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 &lt;router-outlet&gt;

 constructor(
    private router: Router,
    private route: ActivatedRoute,
    private elementRef: ElementRef
  ){
    this.router.events.subscribe((data) =&gt; {
      if (data instanceof RoutesRecognized) {
        this.elementRef.nativeElement.ownerDocument.body.className = data.state.root.firstChild.data[&#39;theme&#39;];
      }
    });
  }

答案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.

huangapple
  • 本文由 发表于 2023年2月24日 05:09:20
  • 转载请务必保留本文链接:https://go.coder-hub.com/75550352.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定