I have created a custom radio component that just changes the style of our radio buttons to have checkmarks in them. I implemented ControlValueAccessor so that I could use the element with Reactive Forms, and have the component working properly when you click on the radio buttons in the UI. The problem I have is that when I try and set the value from my component rather than through a UI interaction (specifically trying to reset the form) the value changes properly on the reactive form, but the UI isn't updated.
Here is my custom radio control:
import { ChangeDetectorRef, Component, EventEmitter, forwardRef, Input, OnInit, Output } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
@Component({
selector: 'k-checkmark-radio',
templateUrl: './checkmark-radio.component.html',
styleUrls: ['./checkmark-radio.component.scss'],
providers: [{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => CheckmarkRadioComponent),
multi: true
}]
})
export class CheckmarkRadioComponent implements OnInit, ControlValueAccessor {
@Input() groupName: string = "";
@Input() label: string = "";
@Input() valueName: string = "";
@Input() radioId!: string;
public checked: boolean;
public value!: string;
constructor( private _cd: ChangeDetectorRef) { }
onChange: any = () => {}
onTouch: any = () => {}
onInputChange(val: string){
this.checked = val == this.valueName;
this.onChange(val);
}
writeValue(value: string): void {
this.value = value;
this.checked = value == this.valueName;
console.log(`${this.valueName} Writing Checkmark Value: `, value, this.checked);
this._cd.markForCheck();
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouch = fn;
}
ngOnInit(): void {
}
}
and here is the template for it:
<div class="form-check form-check-inline">
<label>
<input
type="radio"
[id]="groupName + '_' + valueName"
(ngModelChange)="onInputChange($event)"
[name]="groupName"
[value]="valueName"
[(ngModel)]="value">
<span class="label-size">{{ label }}</span>
</label>
</div>
<br /> Checked? {{ checked }}
I setup a working example of the problem here: https://stackblitz.com/edit/angular-ivy-23crge?file=src/app/checkmark-radio/checkmark-radio.component.html and you can recreate the problem by doing the following:
- click on the Inactive radio button (should show blue state properly)
- click on Reset button (both radios will be empty, but you will see the form shows Active correctly)