Skip to content

Value binding required for Reactive Forms #3072

@ArakTaiRoth

Description

@ArakTaiRoth

Info

Reported by Walter and Song Jiang

This was discovered while trying to reset values in a form. This can all be duplicated with the following code in Angular (this is an Angular only problem):

<form [formGroup]="form">
  <goab-form-item label="Last Name" mb="xl">
    <goab-input formControlName="lastName" [trailingContent]="inputTrailing">
      <ng-template #inputTrailing> $ </ng-template>
    </goab-input>
  </goab-form-item>
  <goab-form-item label="First Name" mb="xl">
    <goab-input formControlName="firstName" [value]="this.form.get('firstName')?.value" />
  </goab-form-item>
  <goab-form-item label="Member ID" mb="xl">
    <goab-input-number
      formControlName="memberId"
      [value]="this.form.get('memberId')?.value"
    />
  </goab-form-item>
  <goab-form-item label="Gender" mb="xl">
    <goab-dropdown formControlName="genderId">
      <goab-dropdown-item label="Male" value="1" />
      <goab-dropdown-item label="Female" value="2" />
      <goab-dropdown-item label="Other" value="3" />
    </goab-dropdown>
  </goab-form-item>
  <goab-form-item label="Birth Date" mb="xl">
    <goab-date-picker formControlName="birthDate" />
  </goab-form-item>
</form>
<goab-button (onClick)="resetForm()" mt="2xl">Reset Form</goab-button>
<br />
{{ form.valueChanges | async | json }}
form!: FormGroup;

constructor(private fb: FormBuilder) {
  this.form = this.fb.group({
    lastName: [""],
    firstName: [""],
    memberId: [""],
    genderId: [""],
    birthDate: [""],
  });
}

resetForm() {
  this.form.reset();
}

The issue is, the form reset works fine the first time, but everytime after that, it no longer works on most input types (it works fine for DatePicker). That being said, it does actually reset the value property of the form control, but it doesn't reset the UI, so it looks like the value is still entered (it's not).

This can be alleviated if you bind the [value] property to the value of the associated formControl. But accordingly, binding the value to the input shouldn't be required, as linking the input to a formControl should be enough.

More Info

This is actually really easy to fix, the reason it works properly for the DatePicker is this Angular code:

override writeValue(value: Date | null): void {
  this.value = value;

  const datePickerEl = this.elementRef?.nativeElement?.querySelector("goa-date-picker");

  if (datePickerEl) {
    if (!value) {
      datePickerEl.setAttribute("value", "");
    } else {
      datePickerEl.setAttribute(
        "value",
        value instanceof Date ? value.toISOString() : value,
      );
    }
  }
}

If the above code is just used in our other Angular input components (changed as need for the value types), it fixes the issue (tested by me with the Input component).

Acceptance Criteria:

  1. Assigning a formControl to an input component should be all that's required to access the value and manipulate the value of an input component

Metadata

Metadata

Assignees

Type

Projects

Status

Dev

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions