angular / components

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

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

Open wadefleming-nz opened 2 years ago

wadefleming-nz commented 2 years ago

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

crisbeto commented 2 years ago

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

raysuelzer commented 1 year ago

@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

himittal09 commented 5 months ago

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.