angular material mat radio button unchecked on multiple click
Asked Answered
S

4

6

How can I clear <mat-radio-button> selected on second click (after it is already selected)

I know I can implement this behavior with checkbox but i need to allow select only one item.

Any help?

My code look like :

<mat-radio-group name="WasFamilyMemberPresent">
    <mat-radio-button *ngFor="let item of lookupNoYes" [value]="item.Code" >
       {{item.Desc}}
    </mat-radio-button>
</mat-radio-group>
Seabury answered 4/12, 2018 at 12:6 Comment(2)
Elaborate your requirement and share what you have tried so far.Compote
You're confusing something. You already can select only one item with radio buttons. You cannot deselect all of them, that's just not how they work.Maestas
P
10

** UPDATED ** 10/11/2022

reference Sara's stackblitz answer below.


You can do the following to accomplish this.

Assign a template reference to the button #button and pass it to the component method (click)="checkState(button)"

 <mat-radio-button #button class="example-radio-button" *ngFor="let season of seasons" [value]="season" (click)="checkState(button)">

Create a local variable in the component to store the button value for comparison in checkState()

 currentCheckedValue = null;

DI Renderer2 to remove focus from the button

 constructor(private ren: Renderer2) { }

Wrap logic in setTimeout to put it on the digest cycle, check if local variable exist and if current value equals argument value... if true deselect, remove focus and null local variable... else set local variable for future comparison.

checkState(el) {
    setTimeout(() => {
      if (this.currentCheckedValue && this.currentCheckedValue === el.value) {
        el.checked = false;
        this.ren.removeClass(el['_elementRef'].nativeElement, 'cdk-focused');
        this.ren.removeClass(el['_elementRef'].nativeElement, 'cdk-program-focused');
        this.currentCheckedValue = null;
        this.favoriteSeason = null;
      } else {
        this.currentCheckedValue = el.value
      }
    })
  }

Stackblitz

https://stackblitz.com/edit/angular-c37tsw?embed=1&file=app/radio-ng-model-example.ts

Precipitate answered 4/12, 2018 at 15:43 Comment(4)
Thank you so much, Its work fine! only a little problem: after uncheck, the model (favoriteSeason) not be empty. I add the following row "this.favoriteSeason = null;" in the true condition and it works perfect. Is it the right way? Thanks!Seabury
please see revision to stackblitz and checkState() i added setting this.favoriteSeason = nullPrecipitate
well, it does not work if you have reactive forms... so you need to add another param on checkState like: checkState(el, event: MouseEvent) ... and do event.preventDefault(); there before timeout.... and in the view you need to call it (click)="checkState(button, $event)" ... Hope it helpsSidney
@DS_web_developer can you share the code how reactive form radiobox work because i am stuck with reactive form scenario.Ge
G
9

I have simplified Marshal's code here

https://stackblitz.com/edit/angular-c37tsw-zho1oe

I removed setTimeout and Renderer2 import and it would seem to work even without these but with an event.preventDefault().

Garges answered 6/5, 2020 at 16:37 Comment(1)
Hey, I have used your solution and it works! Thank you very much!Uriisa
I
0

I'm not sure what answer you are looking for since the angular material radio buttons default behaviour is to only allow one selected item. (This is what i assume you are asking based off of your question)

Are you trying to create behaviour where the user can deselect all radio buttons?

Infusionism answered 4/12, 2018 at 15:8 Comment(0)
D
0

I had the same problem as OP and I tried both the most popular and second most popular answers but neither of them worked for me. I'm using Angular 10 and this post is 4 years old so I hope this answer will help someone else who has my problem.

I noticed that the mat-radio-button was being assigned a class 'mat-radio-checked' when you checked it. The reason I believe that the above 2 answers no longer work is that the value of the button is set before you receive it in the ts file so no matter how you try to assign the _checked value to false it isn't going to work. But changing that class is doable. This method also allows you to deselect the button without having to keep track of any kind of global variable. Here's a generic example:

In the html assign each button a reference variable using the # and an on click event passing the event and button reference.

  <mat-radio-group class="radio-group">
    <mat-radio-button #option1 class="radio-item" value="New User" (click)="onRadioClick($event, option1)”>New User</mat-radio-button>
    <mat-radio-button #option2 class="radio-item" value=“Existing User" (click)="onRadioClick($event, option2)”>Existing User</mat-radio-button>
  </mat-radio-group>

Then in the onRadioClick function check to make sure that the button the user clicked has a class 'mat-radio-checked'; if it does then remove the check class and add our own flag marked-unchecked. This way if you uncheck an option then check it again we will know that it has been checked again and can go ahead and add the 'mat-radio-checked' class again.

onRadioClick(event: any, button: any): void {
  let targetButton = event.target;
  while (targetButton && targetButton.parentNode && targetButton.parentNode.classList) {
    targetButton = targetButton.parentNode;
    if (targetButton.classList.contains('mat-radio-checked') && !targetButton.classList.contains('marked-unchecked')) {
      targetButton.classList.remove('mat-radio-checked');
      targetButton.classList.add('marked-unchecked');
      break;
    }
    if (targetButton.classList.contains('marked-unchecked')) {
      targetButton.classList.remove('marked-unchecked');
      targetButton.classList.add('mat-radio-checked');
    }
  }
}

For further explanation on this just inspect your mat-radio-button element in your browser and you'll be able to see the mat-radio-checked css class I was talking about and it should become apparent.

Delative answered 13/10, 2022 at 1:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.