angular / components

Component infrastructure and Material Design components for Angular
https://material.angular.io
MIT License
24.22k stars 6.69k forks source link

Radio Button with object as value uncheckes on reset/setvalue/patchvalue #13432

Open CurtisDS opened 5 years ago

CurtisDS commented 5 years ago

Bug, feature request, or proposal:

Bug

What is the expected behavior?

Just read the next part it will become obvious.

What is the current behavior?

When using objects as the value for MatRadioGroup and MatRadioButton the current implementation lacks a compareWith property like the current implementation of MatSelect. Normally the radio button will only do a reference based comparison of the value compared to the radio groups value to see if a button should be checked. This is an issue because I am using an API to get the values for the radio group and buttons this interferes with this way of doing a comparison.

However MatRadioButton does have a property called checked which I can use. I wrote my own compare method and have it check the current value of the MatRadioGroup with the current value of the MatRadioButton and return true to set the checked state of the radio button.

When I use reset(value), setValue(value), or patchValue(value) or click on a radio to change the value of the MatRadioGroup, everything works. However performing this twice with the same object results in the radio being unchecked.

What are the steps to reproduce?

https://stackblitz.com/edit/angular-material-radio-not-checked-bug

Press the set button twice. OR Press the set button then press the reset button twice OR Change the selected radio by clicking on a new option and then press the reset button twice OR Do not change anything and right away (after a fresh page load) press the reset button

What is the use-case or motivation for changing an existing behavior?

Allowing me to use objects or arrays with MatRadioGroup/MatRadioButton while preserving the functionality of a simple reset button for my form.

Which versions of Angular, Material, OS, TypeScript, browsers are affected?

material 5 and 6

Is there anything else we should know?

This may be related to: https://github.com/angular/material2/issues/11368

I also think that this feature request would also help potentially fix this issue depending on implementation: https://github.com/angular/material2/issues/10495

manklu commented 5 years ago

It works if you always use the same objects as value.

https://stackblitz.com/edit/angular-material-radio-not-checked-bug-luthnw

manklu commented 5 years ago

Alternatively you could do something like this.

https://stackblitz.com/edit/angular-material-radio-not-checked-bug-ks4jxf

crisbeto commented 5 years ago

@manklu is correct: the value is assigned by reference. Closing since it works as expected.

CurtisDS commented 5 years ago

@manklu your first suggestion doesn't work in my use case which I explained better in my feature request https://github.com/angular/material2/issues/10495

Your second solution looks like it would work as a work around.

@crisbeto I understand that the radio group uses references. If you look at the StackBlitz example I linked. I wrote my own compare method. Using the checked attribute of the radio button and the compare method I wrote the button should be checked. It works when initializing. It works when using setValue, reset and patchValue. It works when clicking on the button and changing the value.

However, as I said in my bug report. Which I believe is a bug and should be fixed. It unchecks itself when you use setValue to set the control to a new reference with the same value. The checked property is being ignored. It shouldn't ignore the checked property. Unless there is some reason Im not seeing. If you have a property called checked... and that property is being set to true... what reason would there be to not check that radio button.

CurtisDS commented 5 years ago

So I did some more looking into this. It also seems to be an issue with native radio buttons in angular. At least when using FormControl. https://stackblitz.com/edit/angular-radio-not-checked-bug

So maybe my assumption about the parameter checked is wrong? Or maybe its an Angular problem and not a Material problem?

manklu commented 5 years ago

It also seems to be an issue with native radio buttons in angular. At least when using FormControl.

Reference would be helpful.

CurtisDS commented 5 years ago

Reference would be helpful.

a reference to what? I linked the stackblitz to an example of the exact same thing happening with plain native radio buttons, I dont understand what you are asking sorry

manklu commented 5 years ago

@CurtisDS Sorry, overseen the changes since you still have a big bunch of material stuff in it.

CurtisDS commented 5 years ago

I removed all the material imports now, if it makes it clearer.

manklu commented 5 years ago

Your problem is, that you have two colliding informations which radio button should be selected.

Depending on the exact implementation details, it works as expected or not.

I see only two solutions for you

CurtisDS commented 5 years ago

Ive updated the stackblitz with native radio buttons to make it clearer whats going on with the object references.

The thing is, regardless of if you think the checked property should have precedence or not. The behavior is not consistent. If you press the set button 1 time, it works... it is only when you press it the second time that it unchecks the value.

The default selection is Fall. If you change it to Spring and then press the reset button it sets it back to Fall (lets say ID 5) and it works. Press reset again. The form control is still ID 5, in terms of the value nothing has changed. But the radio gets unchecked.

manklu commented 5 years ago

The behavior is not consistent.

Yes. The form value says not selected and the checked value says selected. It now depends on the details of the implementation what exactly happens in which scenario.

himittal09 commented 2 months ago

I'm presently facing similar issue as mentioned, when using ReactiveForms. If i use the form.reset() or form.patchValue(), the radio buttons are not correctly checked in UI, even if the values are patched correctly. I've been using a single FormControl Inside FormArray (required)

My Markup:

<div formArrayName="correctAnswer">
        <mat-label>Correct Answer</mat-label>
        <mat-radio-group aria-label="Select an option" required formControlName="0" matInput #inspectInput>
            @for (item of answerOptions.controls; track item; let i = $index) {
            <mat-radio-button [value]="i">{{item.value}}</mat-radio-button>
            }
        </mat-radio-group>
    </div>

and my Typescript (Angular)


      @ViewChild('inspectInput') someInput!: ElementRef<MatRadioGroup>;

      ...

      let w = JSON.stringify(this.questionForm.controls.correctAnswer);
      let x = JSON.stringify(this.someInput.nativeElement);
      this.questionForm.reset();
      this.questionForm.patchValue(this._question);
      let y = JSON.stringify(this.questionForm.controls.correctAnswer);
      let z = JSON.stringify(this.someInput.nativeElement);

Value of w and y, and value of x and z are same in the console; and commenting out either the reset or patchValue line doesn't checks the radio buttons.