简体   繁体   中英

change colour of a mat button when clicked in angular

Hi I am developing an angular application. I want to create tabs, clicking on each calls a different function. I am using mat buttons for it. My code


<div flexLayout="row">
    <button mat-flat-button [color]="this.paletteColour" (click)="change()">B2-L1</button>
    <button mat-flat-button [color]="this.paletteColour" (click)="change()">B2-L3</button>
    <button mat-flat-button [color]="this.paletteColour" (click)="change()">B2-L3</button>
    <button mat-flat-button [color]="this.paletteColour" (click)="change()">B2-L4</button>

</div>

.ts file

 paletteColour
  change() {
  this.paletteColour = 'warn';
  }

.css file

.mat-flat-button {
    background-color: grey;
    border-radius: 0 px !important;;  
}

.mat-button, .mat-flat-button, .mat-icon-button, .mat-stroked-button { border-radius: 0px; }

but this changes colour of all the buttons when clicked on one button. How do I change the color of only one button that has been clicked and rest all remain the same colour.

PS: Colour change is working only when i comment background-colour in css.

According to your requirment, first you need to know which tab is active and then apply color only for that tab,for that purpose you need to have another variable currentActiveTab . You need to change the currentActiveTab value whenever user clicks on a different tab using change method and this will activate the color of tab by passing the tab index as param to the method.

<div flexLayout="row">
    <button mat-flat-button [color]="this.crrentActiveTab == 1 ? this.paletteColour : null" (click)="change(1)">B2-L1</button>
    <button mat-flat-button [color]="this.crrentActiveTab == 2 ? this.paletteColour : null" (click)="change(2)">B2-L3</button>
    <button mat-flat-button [color]="this.crrentActiveTab == 3 ? this.paletteColour : null" (click)="change(3)">B2-L3</button>
    <button mat-flat-button [color]="this.crrentActiveTab == 4 ? this.paletteColour : null" (click)="change(4)">B2-L4</button>
</div>

Here you will be setting the paleteinside the ts change method

 change(index) {
  this.currentActiveTab = index;
 }

you cannot apply class(color attribute of mat) like above in angular.It should use as like below

 <div flexLayout="row">
          <button mat-flat-button [attr.color]="this.selected == 1 ? 'warn' : 'primary'" (click)="change(1)">B2-L1</button>
          <button mat-flat-button [attr.color]="this.selected == 2 ? 'warn' : 'primary'" (click)="change(2)">B2-L3</button>
          <button mat-flat-button [attr.color]="this.selected == 3 ? 'warn' : 'primary'" (click)="change(3)">B2-L3</button>
          <button mat-flat-button [attr.color]="this.selected == 4 ? 'warn' : 'primary'" (click)="change(4)">B2-L4</button>
      </div>

change(n) {
    this.paletteColour = 'warn';
    this.selected=n;
  }

You could put the buttons in their own components. I made a quick demo with a simple button. I am sure it works similar with angular material.

A major advantage is that this also separates functionality instead of making a component class that does everything.

import { Component } from '@angular/core';

@Component({
  selector: 'my-button',
  template: '<button [style.background]="this.color" (click)="toggleColor()">I am button #1</button>'
})
export class MyButtonComponent  {
  color = 'red';

  constructor(){}

  toggleColor(){
    if( this.color === 'red' )
      this.color = 'blue';
    else
      this.color = 'red';
  }
}

Play around with it: https://stackblitz.com/edit/angular-y8zf5a

Note: Personally I would not colour the buttons based on a button-click, but change the buttons class to indicate the availability of the function, which the button calls. So you would have classes like unavailable, processing, available, processed, etc. that reflect the state of the button. These classes would be styled with css.

use deep

 .mat-flat-button  /deep/ .mat-button-focus-overlay {
          background-color: grey;
          border-radius: 0 px !important;; 
    }

this will override the default style

I figured out a way

.html

<div flexLayout="row">
    <div flexLayout="row">
        <button mat-flat-button [ngClass]="this.selected == 1 ? 'tab_selected' : 'tab_unselected'" (click)="change(1)">B2-L1</button>
        <button mat-flat-button [ngClass]="this.selected == 2 ? 'tab_selected' : 'tab_unselected'" (click)="change(2)">B2-L3</button>
        <button mat-flat-button [ngClass]="this.selected == 3 ? 'tab_selected' : 'tab_unselected'" (click)="change(3)">B2-L3</button>
        <button mat-flat-button [ngClass]="this.selected == 4 ? 'tab_selected' : 'tab_unselected'" (click)="change(4)">B2-L4</button>
    </div>
</div>

.ts

selected
change(n) {
  this.paletteColour = 'warn';
  this.selected=n;
  console.log(this.selected);
}

.css

   .tab_selected {
    background-color: grey; 
    border-radius: 0 px !important;;  
}

 .mat-button {
  border-radius: 0 px !important;;     
} 

Thank you all for the support.

Since you mentioned you were specifically using navigation I have another solution for you; You can make angular add a class named active when a route is active. This is achieved by routerLinkActive="active" .

Stackblitz: https://stackblitz.com/edit/angular-ijn9bz

app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
import { RouterModule } from '@angular/router'

import { AppComponent } from './app.component';
import { HelloComponent } from './hello.component';
import { HomeComponent } from './home/home.component';
import { Page2Component } from './page2/page2.component';
import { Page3Component } from './page3/page3.component';

@NgModule({
  imports:      [ 
    BrowserModule, 
    FormsModule,
    RouterModule.forRoot([
      { path: 'home', component: HomeComponent },
      { path: 'page2', component: Page2Component },
      { path: 'page3', component: Page3Component }
    ])
  ],
  declarations: [ AppComponent, HelloComponent, HomeComponent, Page2Component, Page3Component ],
  bootstrap:    [ AppComponent ]
})
export class AppModule { }

app.component.html

<div flexLayout="row">
    <button [routerLink]="['/home']" routerLinkActive="active">B2-L1</button>
    <button [routerLink]="['/page2']" routerLinkActive="active">B2-L3</button>
    <button [routerLink]="['/page3']" routerLinkActive="active">B2-L3</button>
</div>

<router-outlet></router-outlet>

app.component.css

.active{
  background: yellow;
}
  • Ver easy solution would be like the following:-

  • Just use routeLinkActive='active' and set a class in the component css called active.

     <button mat-raised-button color="primary" *appHasRole="'admin'" routerLink="/admin" routerLinkActive="active" [routerLinkActiveOptions]={exact:true} >Home </button>

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