skip to Main Content

My Angular Material v18 application allows the user to set their theme but one component group, the "order control", needs to be independent of the theme. Here’s an HTML version that kinda does what it should followed by an Angular Material section which does not change color.

How can I get the Angular Material order control to change color when BUY/SELL is selected, similarly to the HTML version?

<main>
  <section>
    <h1>HTML</h1>
    <div class="order-control">
      <div>
        <span [class]="buyColor()" (click)="isSell=false">BUY</span>
        <span [class]="sellColor()" (click)="isSell=true">SELL</span>
      </div>
      <div>
        <label for="units">Units</label>
        <input
          [class]="getColor()"
          type="range"
          id="units"
          name="units"
          [min]="unitsMin"
          [max]="unitsMax"
          [(ngModel)]="units"
        />
      </div>
      <div>
        <label for="price">Price</label>
        <input
          [class]="getColor()"
          type="range"
          id="price"
          name="price"
          [min]="priceMin"
          [max]="priceMax"
          [(ngModel)]="price"
        />
      </div>
      <div>
        <button [class]="getColor()" type="button">Submit order</button>
      </div>
    </div>
  </section>

  <section>
    <h1>Angular Material</h1>

    <div class="order-control">
      <div>
        <mat-button-toggle-group
          name="side"
          aria-label="Font Style"
          [(ngModel)]="isSell"
        >
          <mat-button-toggle [value]="false">BUY</mat-button-toggle>
          <mat-button-toggle [value]="true">SELL</mat-button-toggle>
        </mat-button-toggle-group>
      </div>

      <div>
        <label for="units">Units</label>
        <mat-slider
          [max]="unitsMax"
          [min]="unitsMin"
          [step]="unitsStep"
          discrete
          showTickMarks
        >
          <input matSliderThumb [(ngModel)]="units" #unitsSlider />
        </mat-slider>
      </div>

      <div>
        <label for="price">Price</label>
        <mat-slider
          class="example-margin"
          [max]="priceMax"
          [min]="priceMin"
          [step]="priceStep"
          discrete
          showTickMarks
        >
          <input matSliderThumb [(ngModel)]="price" #priceSlider />
        </mat-slider>
      </div>

      <div>
        <button mat-flat-button>Submit Order</button>
      </div>
    </div>
  </section>
</main>

CSS

.order-control {
  display: flex;
  flex-direction: column;
  justify-content: center;

  .sell {
    color: red;
    accent-color: red;
  }

  .buy {
    color: blue;
    accent-color: blue;
  }
}
import 'zone.js';
import { Component } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
import { provideAnimationsAsync } from '@angular/platform-browser/animations/async';
import { NgClass } from '@angular/common';
import { FormsModule } from '@angular/forms';

import { MatButtonModule } from '@angular/material/button';
import { MatButtonToggleModule } from '@angular/material/button-toggle';
import { MatCardModule } from '@angular/material/card';
import { MatRadioModule } from '@angular/material/radio';
import { MatSliderModule } from '@angular/material/slider';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    FormsModule,
    NgClass,
    MatButtonModule,
    MatButtonToggleModule,
    MatCardModule,
    MatRadioModule,
    MatSliderModule,
  ],
  templateUrl: './main.html',
  styleUrl: './main.css',
})
export class App {
  isSell: boolean = false;

  units = 1;
  unitsMin = 1;
  unitsMax = 10;
  unitsStep = 1;

  price = 500;
  priceMin = 0;
  priceMax = 1000;
  priceStep = 25;

  buyColor() {
    return this.isSell ? '' : 'buy';
  }

  sellColor() {
    return this.isSell ? 'sell' : '';
  }

  getColor() {
    return this.isSell ? 'sell' : 'buy';
  }
}

Here’s a working sample.

2

Answers


  1. I would advise against doing so, since it would break the design : when you implement a design system, there’s no "independent component", it should all follow the design provided.

    That being said, just apply your class conditionnally ?

    <mat-button-toggle [value]="true" [class.sell]="isSell">SELL</mat-button-toggle>
    
    Login or Signup to reply.
  2. You can try to create a custom theme for the specific components like so

    @use '@angular/material' as mat;
    @include mat.core();
    
    $custom-palette: (
      50: var(--Your-colors),
      ...
    )
     
    $custom-primary: mat.define-palette($custom-palette, 500)
    
    $theme: mat.define-light-theme((
      color: (
        primary: $custom-primary,
        accent: $custom-accent,
      ),
    ))
    
    
    $buy: mat.define-palette($theme, 500)
    
    @include mat-button-theme($buy)
    
    .buy-theme {
      @include mat-button-theme($buy);
    }
    

    Then add logic that assign CSS variables here --Your-colors

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search