7

I have a button on my screen where if the user has already added clicked on it, it is a mat-filled-button but if I haven't clicked on it, it is a mat-button

My code looks like this

 <button
          *ngIf="myVote !== 'UPVOTE'"
          mat-button
          color="primary"
          (click)="onVote('UPVOTE')"
        >
          UPVOTE
        </button>
        <button
          *ngIf="myVote === 'UPVOTE'"
          mat-flat-button
          color="primary"
          (click)="onVote('NONE')"
        >
          UPVOTE
        </button>

Basically I have two buttons and only one shows. Obviously, this is very ugly.

Is there a way where I can achieve the same outcome with only one button and it conditionally is a mat-flat-button or a mat-button based on a set of logic?

Adrita Sharma
  • 21,581
  • 10
  • 69
  • 79
Diskdrive
  • 18,107
  • 27
  • 101
  • 167
  • these might help: https://stackoverflow.com/questions/44597077/apply-a-directive-conditionally and https://stackoverflow.com/questions/37021355/angular-2-how-to-conditionally-apply-attribute-directive – Jojofoulk Sep 13 '19 at 06:36
  • Have a look at this: https://stackoverflow.com/questions/36745734/how-to-add-conditional-attribute-in-angular-2/36745752 – John Sep 13 '19 at 06:43
  • Why not use button toggle instead: https://material.angular.io/components/button-toggle/overview? – 31piy Sep 13 '19 at 07:04
  • Have you tried the solution? – Adrita Sharma Sep 13 '19 at 08:45
  • As of today (angular 15) no good solution does exists. [here](https://github.com/angular/components/issues/15367) if you wish to follow the github feature request – Raphaël Balet Feb 10 '23 at 13:17

3 Answers3

10

Try like this:

<button
  mat-button 
  [class.mat-flat-button]="myVote === 'UPVOTE'"
  color="primary"
  (click)="onVote(myVote === 'UPVOTE'? 'NONE' :'UPVOTE')"
>
  UPVOTE
</button>

See Working Demo

_ I have used raised button the demo for better visibility.

Adrita Sharma
  • 21,581
  • 10
  • 69
  • 79
0

An alternative to the accepted answer would be to use [ngClass]. Making use of ngClass gives you more flexibility and control for future changing requirements.

Taking the answer and just modifying it to use ngClass instead would look like this:

<button
  mat-button 
  [ngClass]="{'mat-flat-button': myVote === 'UPVOTE'}"
  color="primary"
  (click)="onVote(myVote === 'UPVOTE'? 'NONE' :'UPVOTE')"
>
  UPVOTE
</button>

The reason I would recommend this over simply using the [class] attribute, is it makes it easier if you want to apply new conditions to the button in the future. For example, you want a different mat class when the upvote is 'NONE'

You can now easily just add to the object and it becomes:

<button
  mat-button 
  [ngClass]="{'mat-flat-button': myVote === 'UPVOTE', 'mat-stroked-button': myVote === 'NONE'}"
  color="primary"
  (click)="onVote(myVote === 'UPVOTE'? 'NONE' :'UPVOTE')"
>
  UPVOTE
</button>

See the documentation for ngClass here: https://angular.io/api/common/NgClass

Newteq Developer
  • 2,257
  • 1
  • 26
  • 32
-1

From this answer: https://stackoverflow.com/a/36745752/1471485

You could do something like this:

<button
  [attr.mat-button]="myVote !== 'UPVOTE'"
  [attr.mat-flat-button]="myVote === 'UPVOTE'"
  color="primary"
  (click)="onVote()"> <!-- Alternate the vote in the function -->
  UPVOTE
</button>

onVote(){
   if(this.myVote === 'UPVOTE') this.myVote = 'NONE';
   else this.myVote = 'UPVOTE';
}
John
  • 10,165
  • 5
  • 55
  • 71
  • Hi, so I think conceptually your answer is better than Adrita Sharma's answer - she is updating the class which basically requires an understanding of what mat-button and mat-flat-button is doing under the surface. However, your answer doesn't actually work because mat-button and mat-flat-button are selectors within the MatButton component which I don't think you can make conditional... – Diskdrive Sep 14 '19 at 11:10
  • 1
    i dunno, i'm just looking through https://github.com/angular/components/blob/master/src/material/button/button.ts now but it does seem like it only checks to see if that selector is there and if so, adds a class – Diskdrive Sep 14 '19 at 11:11
  • with `[attr.mat-button]` & `[attr.mat-icon-button]` it does not work, unfortunately. For example there are some directives which work with this notation like `[attr.mat-align-tabs] ` but mat-button not work. – Igor Kurkov May 03 '20 at 07:25