angularradio-buttonangular-formsangular14angular15

NG_VALUE_ACCESSOR not returning value to parent component for radio buttons


in the parent component I created a form that should work for 3 pairs of radio buttons. I wanted to do it using NG_VALUE_ACCESSOR, the communication from parent to child works for me, but when I want to print the values from the child components in the parent on the button, they do not change and are always false. Below I attach the code of the parent and child components. But if there is a better approach, I am open to other possibilities. Thanks for help

parent.html

form [formGroup]="plannedMaintenanceForm">
        <rds-service-advisor-planned-maintenance
            [operations]="presentOperations"
            formControlName="presentOperation"
            ></rds-service-advisor-planned-maintenance>
        <rds-service-advisor-planned-maintenance
            [operations]="uncompletedOrDelayedOperations"
            formControlName="uncompletedOperation"
            ></rds-service-advisor-planned-maintenance>
        <rds-service-advisor-planned-maintenance
            [operations]="upcomingOperations"
            formControlName="upcomingOperation"
            ></rds-service-advisor-planned-maintenance>
        <button class="ButtonSquareRefClient ButtonSquareRefClient_primary approve-button" (click)="test()">
            <span>{{ 'common.save' | rdsTranslate }}</span>
        </button>
    </form>

parent.ts

plannedMaintenanceForm = new FormGroup({
        presentOperation: new FormControl(false),
        upcomingOperation: new FormControl(false),
        uncompletedOperation: new FormControl(false)
    });

test(): void {
        console.log(this.plannedMaintenanceForm.value)
    }

child.ts

import { Component, Input, OnInit, forwardRef } from '@angular/core';
import { ControlValueAccessor, FormGroup, NG_VALUE_ACCESSOR } from '@angular/forms';
import { PlannedMaintenance } from 'model/planned-maintenance.model';

@Component({
    selector: 'rds-service-advisor-planned-maintenance',
    templateUrl: './planned-maintenance.component.html',
    styleUrls: ['./planned-maintenance.component.scss'],
    providers: [
        {
            provide: NG_VALUE_ACCESSOR,
            multi: true,
            useExisting: PlannedMaintenanceComponent,
        },
    ],
})
export class PlannedMaintenanceComponent implements ControlValueAccessor {
    @Input() readonly operations: Array<PlannedMaintenance>;
    value: boolean;
    onChanged: any = () => {
        // empty
    };
    onTouched: any = () => {
        // empty
    };

    constructor() {}

    writeValue(value) {
        this.value = value;
        console.log(value)
    }

    registerOnChange(fn: any): void {
        this.onChanged = fn;
        console.log(this.value)
    }

    registerOnTouched(fn: any): void {
        this.onTouched = fn;
    }

    radioButtonChange(val: boolean): void {
      this.value = val;
    }
}

child.html

<div class="planned-radio-buttons">
        <mat-radio-group [(ngModel)]="value" (ngModelChange)="registerOnChange($event)">
            <mat-radio-button [value]="true" class="planned-radio-button">{{'vehicle.customer-approval' | rdsTranslate}}</mat-radio-button>
            <mat-radio-button [value]="false" class="planned-radio-button">{{'vehicle.customer-refusal' | rdsTranslate}}</mat-radio-button>
        </mat-radio-group>      
        
    </div>

Solution

  • So the problem was to use directly registerOnChange, solution is to use onChanged function.