components
components copied to clipboard
bug(mat-radio-group): Programmatic changes are not reflected in the form model
Description
When setting value
on matRadioGroup
, the visually selected radio button updates, but the form model does not.
Looking at the material source code, the form model is only updated (via _controlValueAccessorChangeFn
) via the radio input's change
event. Is this intentional?
Reproduction
See Stackblitz: https://stackblitz.com/edit/angular-ivy-hpd53z?file=src%2Fapp%2Fapp.component.ts
Steps to reproduce:
- Select a radio button by clicking it - observe that the form model updates accordingly
- Select a radio button that is not green
- Click the 'Force Green' button, which programmatically sets the
value
to green
Expected Behavior
The color
value in the form model updates
Actual Behavior
The color
value in the form model does not update
Environment
- Angular: 13.2.0
- CDK/Material: 13.2.5
- Browser(s): Chrome
- Operating System: Windows
Giving this a lower priority, because the idea is that you'd use either the value
or a FormControl
/ngModel
, not both.
@crisbeto This is impacting a bunch of places even when you are not using both. See this...
https://stackblitz.com/edit/components-issue-dtbkuj?file=src%2Fapp%2Fexample-component.html,src%2Fapp%2Fexample-component.ts
When updating value via a FormControl, the Radio button doesn't gets checked (updated) visually if the initial value supplied was not mentioned in the HTML. Just stumbled upon it today.
<div [formGroup]="group">
<mat-label>Correct Answer</mat-label>
<mat-radio-group aria-label="Select an option" required matInput formControlName="v1">
<mat-radio-button value="0" checked="true">A</mat-radio-button>
<mat-radio-button value="1" checked="false">B</mat-radio-button>
</mat-radio-group>
<mat-label>Correct Answer</mat-label>
<mat-radio-group aria-label="Select an option" value="0" required matInput FormControlName="v2">
<mat-radio-button value="0">A</mat-radio-button>
<mat-radio-button value="1">B</mat-radio-button>
</mat-radio-group>
</div>
import { ChangeDetectionStrategy, Component, ViewEncapsulation } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { MatInputModule } from '@angular/material/input';
import { MatRadioModule } from '@angular/material/radio';
@Component({
selector: 'app-dummy',
standalone: true,
imports: [
MatRadioModule,
MatInputModule,
ReactiveFormsModule
],
templateUrl: './dummy.component.html',
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None
})
export class DummyComponent {
group = new FormGroup({
v1: new FormControl('0'),
v2: new FormControl('0')
})
ngAfterViewInit () {
console.log(this.group.controls.v1.value, this.group.controls.v2.value);
setTimeout(() => {
this.group.controls.v1.setValue('1');
this.group.controls.v2.setValue('1');
console.log(this.group.controls.v1.value, this.group.controls.v2.value);
}, 2000);
}
}
And Even, if the checked attribute in