components icon indicating copy to clipboard operation
components copied to clipboard

bug(mat-radio-group): Programmatic changes are not reflected in the form model

Open wadefleming-nz opened this issue 2 years ago • 3 comments

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:

  1. Select a radio button by clicking it - observe that the form model updates accordingly
  2. Select a radio button that is not green
  3. 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

wadefleming-nz avatar Mar 08 '22 03:03 wadefleming-nz

Giving this a lower priority, because the idea is that you'd use either the value or a FormControl/ngModel, not both.

crisbeto avatar Mar 15 '22 10:03 crisbeto

@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

raysuelzer avatar Sep 06 '23 23:09 raysuelzer

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 was supplied, it works as intended, but if value attribute was supplied in , then it breaks.

himittal09 avatar Apr 29 '24 17:04 himittal09