7

I am trying to use Angular Material 2 with my Angular 2 application.

I did not found how to change material theme globally (primaryColor, etc). I know that Angular Material 2 is still in alpha, but is there currently a way to do that?

perror
  • 7,071
  • 16
  • 58
  • 85
quen2404
  • 245
  • 1
  • 2
  • 11
  • Have you read the docs for angular material 1? Maybe it's similar. If there aren't docs for 2 yet, try looking at the source code to figure it out. Or raise an issue on their github project. – Will Sheppard Apr 29 '16 at 13:36

3 Answers3

6

Here's an example of dynamic Angular Material theme implementation as of Angular 5.1 and Angular Material 5.0.

(edit) - Currently tested and working in angular 7+ as well.

Working editable example - https://stackblitz.com/edit/dynamic-material-theming

In theme.scss file, include a default theme(notice it isn't kept under a class name - this is so Angular will use it as the default), and then a light and dark theme.

theme.scss

@import '~@angular/material/theming';
@include mat-core();

// Typography
$custom-typography: mat-typography-config(
  $font-family: Raleway,
  $headline: mat-typography-level(24px, 48px, 400),
  $body-1: mat-typography-level(16px, 24px, 400)
);
@include angular-material-typography($custom-typography);

// Default colors
$my-app-primary: mat-palette($mat-teal, 700, 100, 800);
$my-app-accent:  mat-palette($mat-teal, 700, 100, 800);

$my-app-theme: mat-light-theme($my-app-primary, $my-app-accent);
@include angular-material-theme($my-app-theme);

// Dark theme
$dark-primary: mat-palette($mat-blue-grey);
$dark-accent:  mat-palette($mat-amber, A200, A100, A400);
$dark-warn:    mat-palette($mat-deep-orange);

$dark-theme:   mat-dark-theme($dark-primary, $dark-accent, $dark-warn);

.dark-theme {
  @include angular-material-theme($dark-theme);
}

// Light theme
$light-primary: mat-palette($mat-grey, 200, 500, 300);
$light-accent: mat-palette($mat-brown, 200);
$light-warn: mat-palette($mat-deep-orange, 200);

$light-theme: mat-light-theme($light-primary, $light-accent, $light-warn);

.light-theme {
  @include angular-material-theme($light-theme)
}

In the app.component file, include OverlayContainer from @angular/cdk/overlay. You can find Angular's documentation for this here https://material.angular.io/guide/theming; though their implementation is a little different. Please note, I also had to include OverlayModule as an import in app.module as well.

In my app.component file, I also declared @HostBinding('class') componentCssClass; as a variable, which will be used to set the theme as a class.

app.component.ts

import {Component, HostBinding, OnInit} from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Version } from './classes/version';
import { OverlayContainer} from '@angular/cdk/overlay';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {

  constructor(private http: HttpClient, public overlayContainer: OverlayContainer) {}

  title = 'app';
  version: Version;
  @HostBinding('class') componentCssClass;

  ngOnInit() {
    this.getVersion();
  }

  onSetTheme(theme) {
    this.overlayContainer.getContainerElement().classList.add(theme);
    this.componentCssClass = theme;
  }

  getVersion() {
    this.http.get<Version>('/api/version')
      .subscribe(data => {
        this.version = data;
      });
  }

}

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { HttpClientModule } from '@angular/common/http';

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';

import { AppComponent } from './app.component';

import { OverlayModule } from '@angular/cdk/overlay';

@NgModule({
  declarations: [
    AppComponent,
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    BrowserAnimationsModule,
    MatCardModule,
    MatButtonModule,
    OverlayModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule {}

Finally, call the onSetTheme function from your view.

app.component.html

<button mat-raised-button color="primary" (click)="onSetTheme('default-theme')">Default</button>
<button mat-raised-button color="primary" (click)="onSetTheme('dark-theme')">Dark</button>
<button mat-raised-button color="primary" (click)="onSetTheme('light-theme')">Light</button>

You might consider using an observable so that the functionality would be more dynamic.

K. Waite
  • 1,574
  • 13
  • 12
  • While this may answer the question, [it would be preferable](http://meta.stackoverflow.com/q/8259) to include the essential parts of the answer here, and provide the link for reference. – Tom Aranda Dec 11 '17 at 18:18
  • Sorry, I've provided more detail in the post. – K. Waite Dec 11 '17 at 18:40
  • Please don't post identical answers to multiple questions. Post one good answer, then vote/flag to close the other questions as duplicates. If the question is not a duplicate, *tailor your answers to the question.* – Andrew Myers Dec 12 '17 at 20:43
  • This is cool, but correct me if I'm wrong; this still doesn't give us control to, for example, allow a user to choose their accent/primary colors independently of each other does it? Unless we create a theme for every color combination, users are still locked into predefined themes? I would love for our users to be able to create their own themes. – Jus10 Jan 13 '19 at 03:18
  • Unfortunately, @Jus10 - This isn't currently possible, but there has been talk about integrating custom properties into the library for just that. Looks like they are aiming for ~2020, when IE support dies. https://github.com/angular/material2/issues/4352#issuecomment-449310193 – K. Waite Jan 14 '19 at 15:47
  • You use `color="primary"` but that variable is never defined as far as I can see. Why does that work for you? I have seen this a lot in other people's source code, but I can't get this to work in my own app, I can only reference `dark-primary` directly, which of course then doesn't change when I switch the theme. – Tare Apr 30 '19 at 07:07
  • @Tare In the theme.scss file, we have `@include angular-material-theme($dark-theme)` which will use Angular's theming mixin to set the 'primary' color from `$dark-theme: mat-dark-theme($dark-primary, $dark-accent, $dark-warn);`. That's why using `color="primary"` will work - It's some of the under the hood angular magic that goes on. – K. Waite Apr 30 '19 at 14:44
  • @K.Waite thanks, but I have that and it doesn't work for me. I don't even get the `$primary` variable in the first place though, so probably I'm missing something else as well. Also, I'm trying to use `$primary` in another .scss file, not directly in the html tag. Perhaps that is the problem? – Tare May 02 '19 at 07:01
  • @K.Waite I got it to work now by creating a new scss file which imports material/heming and defines `@mixin new-theme-name` and then imported this new file in my themes.scss file as well as using the `@include new-theme-name($my-app-theme)` (and dark-theme) commands. afterwards i could define the variables but get the original colors in the mixin scope with `$primary: map-get($theme, primary);` – Tare May 02 '19 at 09:19
4

https://github.com/angular/material2/issues/287

@samio80 The styles are currently written with theming in mind, but we don't have a deployment strategy for theming ready yet. As a workaround in the meantime, you can pull the source directly and customize the theme by modifying _default-theme.scss and creating npm packages (via the script stage-release.sh).

Keep in mind that we're still early in the alpha process and, as such, the APIs or behaviors can change between releases.

Günter Zöchbauer
  • 623,577
  • 216
  • 2,003
  • 1,567
1

Here is the link to the angular material theming guide - https://material.angular.io/guide/theming

And here is a sample app that implements the theming approach described in the guide - https://github.com/jelbourn/material2-app

Alexander Kravets
  • 4,245
  • 1
  • 16
  • 15