ionic-team / stencil-ds-output-targets

These are output targets that can be added to Stencil for React and Angular.
https://stenciljs.com
MIT License
244 stars 108 forks source link

bug: RadioValueAccessor generated by angular-output-target overwrites the value of the radio input #434

Open adarean5 opened 1 month ago

adarean5 commented 1 month ago

Prerequisites

Stencil Version

4.18.0

Stencil Framework Output Target

Angular

Stencil Framework Output Target Version

0.8.4

Current Behavior

When the angular FormControl is updated, the RadioValueAccessor overwrites the value attribute of any custom Stencil radio button components bound to the form control.

For example, if the radio inputs are defined like this:

  <fieldset class="radio-group">
    <legend>Custom radio buttons</legend>
    <cust-radio [formControl]="form.controls.customRadio" name="custom-radio" value="option-1" label="Option 1"></cust-radio>
    <cust-radio [formControl]="form.controls.customRadio" name="custom-radio" value="option-2" label="Option 2"></cust-radio>
    <cust-radio [formControl]="form.controls.customRadio" name="custom-radio" value="option-3" label="Option 3"></cust-radio>
  </fieldset>

And the form control is defined like this:

form = new FormGroup({
    customRadio: new FormControl('option-1'),
  })

Then the values in the rendered HTML are overridden to the value of the FormControl (in this case "option-1"). image

Since the values of all inputs are overwritten the value of the form control will remain "option-1" no matter which radio button is clicked.

Expected Behavior

The RadioValueAccessor should not overwrite the value attribute of a custom Stencil radio button component. Instead, it should only change the checked property.

Using native HTML radio inputs with Angular formContol in the same way works as expected and the value attribute of the native inputs is not overwritten. When a radio input is clicked, the form control is updated with the value of the radio input.

Steps to Reproduce

This code reproduction repository contains a stencil-library package and an angular-workspace package. The custom radio button component can be found in packages/stencil-library/src/components/cust-radio/cust-radio.component.tsx The value accessor config is defined in packages/stencil-library/stencil.config.ts using the valueAccessorConfigs property. The custom radio component is used in packages/angular-workspace/projects/my-app/src/app/app.component.html. The angular form group is defined in packages/angular-workspace/projects/my-app/src/app/app.component.ts

Steps to reproduce:

Code Reproduction URL

https://github.com/adarean5/stencil-angular-radio-bug

Additional Information

As mentioned above, this behavior does not match the behaviour of using the Angular formControl with native HTML radio inputs (described here).

The Angular value accessor for radio inputs does not override the value of the native radio input. Instead, it sets the checked property based on whether the formContol value equals the radio input value. This is the implementation of the writeValue method in Angular's RadioControlValueAccessor, which handles reactive forms integration with native HTML radio inputs (source):

writeValue(value: any): void {
    this._state = value === this.value;
    this.setProperty('checked', this._state);
}

This how the writeValue method of the ValueAccessor accessor class generated by Stencil looks like:

writeValue(value: any) {
    this.el.nativeElement.value = this.lastValue = value == null ? '' : value;
}

The writeValue method of the Stencil-generated ValueAccessor works differently than the writeValue method used by Angular to handle native radio inputs. It overrides the value of the input instead of toggling the checked attribute. The RadioValueAccessor generated by Stencil extends this value accessor and inherits this writeValue method. The RadioValueAccessor generated by stencil should probably override the writeValue method from the ValueAccessor class with an implementation that is similar to the one in Angular.

ionitron-bot[bot] commented 1 month ago

Thanks for the issue!

This project is currently maintained for the purposes of supporting Ionic Framework. At this time, only new issues & pull requests that support Ionic Framework will be prioritized. For the latest updates regarding the maintenance status of this project, please see this section of the project's README