简体   繁体   中英

Angular: How to change material theme and retain some custom css?

I want a user to be able to log into our app, have the material theme change to their company colors while retaining some custom CSS on those material components.

I have a project at work I am working on in which we want to change the material theme based on the user/their company when they log in.
My issue is that when the app loads, it loads the global styles and the material theme, all looks well. But upon login- when I am changing the material theme- the new theme appears to override some of the custom CSS we added to the material components (like background color to mat-rows within mat-tables). I can't figure out how to either retain my custom CSS or keep the material theme for overriding it. Right now I am working on a single class getting overwritten, but will expand to everything else once I find the solution.
I have tried:
- pulling the custom class into a lazy loaded stylesheet, loaded right after the theme changes.
- adding ::ng-deep to the class in styles.scss.
- adding ::ng-deep to the class in the lazy loaded stylesheet.

styles.scss

.matRowDefault {
    margin-bottom: .8rem;
    background: white;
    border-radius: 5px;
    height: 50px;
    border-left: 7px solid gray;
}

theme.scss

$dpa-primary: mat-palette($mat-deep-purple);
$dpa-accent: mat-palette($mat-amber);
$dpa-warn: mat-palette($mat-basicRed);

$dpa-theme: mat-light-theme($dpa-primary, $dpa-accent, $dpa-warn);
.dpa-theme {
    @include angular-material-theme($dpa-theme);
}

component.html

<mat-row class="matRowDefault" (mouseenter)="selectRow(row)" (mouseleave)='selectedRow = ""'>
</mat-row>

app.component.ts

  setTheme(theme) {
    if (theme.toLowerCase() != "default-theme") {
      this.overlayContainer.getContainerElement().classList.add(theme);
      this.componentCssClass = theme;

      var customUrl = '../assets/customColors2.css';
      this._srv.loadExternalStyles(customUrl);
    }
  }

beta.service.ts

  loadExternalStyles(styleUrl: string) {
    return new Promise((resolve, reject) => {
      const styleElement = document.createElement('link');
      styleElement.rel = 'stylesheet';
      styleElement.href = styleUrl;
      styleElement.onload = resolve;
      document.head.appendChild(styleElement);
    });
  }

Using the above single style class, the component style overrides the border (which is fine), the new theme overrides the background to background: inherit which makes the rows the same color as the table (not what I want), and then I can see the rest of the styles from the styles.scss still in place.
So it is all working, I just need a clever way to keep the theme from overriding any custom CSS I already have in place.

I think the solution your looking for is Angular's ViewEncapsulation property. There are 4 options: Emulated, Native, None, and ShadowDom.

See here: https://angular.io/api/core/ViewEncapsulation and https://blog.thoughtram.io/angular/2015/06/29/shadow-dom-strategies-in-angular2.html

The fix I think you're looking for would be to use ViewEncapsulation.Native in each component you want to use the custom CSS with. Essentially it will allow you to not apply your global styling to that specific component.

Component.ts

@Component({
  encapsulation: ViewEncapsulation.Native,
  selector: 'app-component',
  templateUrl: './component.html',
  styleUrls: ['./component.scss']
})

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM