0" [formGroup]="m" /> 0" [formGroup]="m" /> 0" [formGroup]="m"/>

Handle mat-radio-button form value accessor in Angular Material

42 views Asked by At

I have a mat radio group component that renders also a list of form fields

<form *ngIf="myRatesForm.controls.items.controls.length > 0" [formGroup]="myRatesForm">
  <mat-radio-group formArrayName="items">
    <div [formGroupName]="i" *ngFor="let myRate of myRatesForm.controls.items.controls; let i = index">
      <mat-radio-button [checked]="myRate.isFavorite" formControlName="isFavorite" [value]="myRate">
        <div class="flex">
          <mat-form-field appearance="outline">
            <input formControlName="name" matInput placeholder="Taux" />
          </mat-form-field>
          <div (click)="inputFocus($event)">
            <mat-form-field appearance="outline">
              <input formControlName="rateValue" matInput placeholder="Taux" />
            </mat-form-field>
          </div>
        </div>
      </mat-radio-button>
    </div>
  </mat-radio-group>
</form>

In my ts file I'm creating a dynamic formArray

itemsForm: FormArray = this.fb.array([]);
myRatesForm = new FormGroup({
  items: this.itemsForm,
});
constructor(private store: Store, private pricesSelector: PricesSelector, private fb: FormBuilder) {}

myRates: MyRates[] = [];
subscription$: Subscription = new Subscription();
favoriteRate: MyRates;
ngOnInit(): void {
  this.subscription$ = this.store.select(this.pricesSelector.getPriceTaxValue).subscribe(data => {
    this.myRates = data.myRates;
    this.myRates.map(rate => {
      this.myRatesForm.controls.items.push(
        this.fb.group({
          name: [rate.name, Validators.required],
          rateValue: [rate.rateValue, Validators.required],
          isFavorite: [rate.isFavorite],
        })
      );
    });
  });
}

Actually the Name and the rateValue formControls are working .

But the radioButton isFavorite is not working . I'm getting this error

NG01203: No value accessor for form control path: 'items -> 2 -> isFavorite'. Find more...

I think because FormControlName is not set on mat-radio-group

Is there a way to do it ?

1

There are 1 answers

0
Naren Murali On BEST ANSWER

Radio group is a logical grouping of mat radio buttons, so we need to move the radio group to a separate form control favourited this will contain the selected value, then we can render the radio buttons without form control name!

working example provided with code and stackblitz!

code

ts

import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import {
  FormArray,
  FormBuilder,
  FormControl,
  FormGroup,
  FormsModule,
  ReactiveFormsModule,
  Validators,
} from '@angular/forms';
import { MatFormFieldModule } from '@angular/material/form-field';
import { MatRadioModule } from '@angular/material/radio';
import { MatInputModule } from '@angular/material/input';
import { Subscription } from 'rxjs';

/**
 * @title Radios with ngModel
 */
@Component({
  selector: 'radio-ng-model-example',
  templateUrl: 'radio-ng-model-example.html',
  styleUrl: 'radio-ng-model-example.css',
  standalone: true,
  imports: [
    FormsModule,
    CommonModule,
    MatFormFieldModule,
    MatRadioModule,
    MatInputModule,
    ReactiveFormsModule,
  ],
})
export class RadioNgModelExample {
  itemsForm: FormArray = this.fb.array([]);
  myRatesForm = new FormGroup({
    favourited: new FormControl(),
    items: this.itemsForm,
  });
  constructor(private fb: FormBuilder) {}

  myRates: any[] = [];
  subscription$: Subscription = new Subscription();
  favoriteRate: any;

  ngOnInit(): void {
    this.myRates = [
      { name: 'test1', rateValue: 1, isFavorite: true },
      { name: 'test2', rateValue: 2, isFavorite: false },
      { name: 'test3', rateValue: 3, isFavorite: false },
    ];
    this.myRates.map((rate) => {
      this.myRatesForm.controls.items.push(
        this.fb.group({
          name: [rate.name, Validators.required],
          rateValue: [rate.rateValue, Validators.required],
          isFavorite: [rate.isFavorite],
        })
      );
    });
  }
}

html

{{myRatesForm.value | json}}

<form
  *ngIf="myRatesForm.controls.items.controls.length > 0"
  [formGroup]="myRatesForm"
>
  <mat-radio-group formControlName="favourited">
    <div formArrayName="items">
      <div
        [formGroupName]="i"
        *ngFor="let myRate of myRatesForm.controls.items.controls; let i = index"
      >
        <mat-radio-button
          [value]="myRates[i]"
          [checked]="myRates[i].isFavorite"
        ></mat-radio-button>
        <div class="flex">
          <mat-form-field appearance="outline">
            <input formControlName="name" matInput placeholder="Taux" />
          </mat-form-field>
          <div>
            <mat-form-field appearance="outline">
              <input formControlName="rateValue" matInput placeholder="Taux" />
            </mat-form-field>
          </div>
        </div>
      </div>
    </div>
  </mat-radio-group>
</form>

Stackblitz Demo