Angular 6 patchValue Not Setting..sometimes
Asked Answered
C

4

5

I have a basic form shown below. I make a call to an API to grab the user's personal info and I want to fill the form fields with the appropriate values. I have been trying to use patchValue but I cannot get it to work.

<form
  (ngSubmit)="(onSubmit)"
  class="example-form"
  [formGroup]="firstFormGroup"
  #registerForm="ngForm"
>
  <mat-form-field class="example-full-width">
    <input matInput placeholder="Company" formControlName="company" required autofocus />
    <mat-error *ngIf="firstFormGroup.get('company').hasError('required')">
      Company name is
      <strong>required</strong>
    </mat-error>
  </mat-form-field>

  <table class="example-full-width" cellspacing="0">
    <tr>
      <td>
        <mat-form-field class="example-full-width">
          <input matInput placeholder="First name" formControlName="first_name" required />
          <mat-error *ngIf="firstFormGroup.get('first_name').hasError('required')">
            First name is
            <strong>required</strong>
          </mat-error>
        </mat-form-field>
      </td>
      <td>
        <mat-form-field class="example-full-width">
          <input matInput placeholder="Last Name" formControlName="last_name" required />
          <mat-error *ngIf="firstFormGroup.get('last_name').hasError('required')">
            Last name is
            <strong>required</strong>
          </mat-error>
        </mat-form-field>
      </td>
    </tr>
    <tr>
      <td>
        <mat-form-field class="example-full-width">
          <input matInput placeholder="Email" formControlName="email" required />
          <mat-error
            *ngIf="firstFormGroup.get('email').hasError('email') && !email.hasError('required')"
          >
            Please enter a valid email address
          </mat-error>
          <mat-error *ngIf="firstFormGroup.get('email').hasError('required')">
            Email is
            <strong>required</strong>
          </mat-error>
        </mat-form-field>
      </td>
    </tr>
  </table>

  <p>
    <mat-form-field class="example-full-width">
      <textarea matInput placeholder="Address" formControlName="address" required></textarea>
    </mat-form-field>
    <mat-form-field class="example-full-width">
      <textarea matInput placeholder="Address 2"></textarea>
    </mat-form-field>
  </p>

  <table class="example-full-width" cellspacing="0">
    <tr>
      <td>
        <mat-form-field class="example-full-width">
          <input matInput placeholder="City" formControlName="city" required />
        </mat-form-field>
      </td>
      <td>
        <mat-form-field class="example-full-width">
          <mat-select placeholder="State" formControlName="state" required>
            <mat-option>None</mat-option>
            <mat-option *ngFor="let state of states" [value]="state">{{ state }}</mat-option>
          </mat-select>
        </mat-form-field>
      </td>
      <td>
        <mat-form-field class="example-full-width">
          <input
            matInput
            #postalCode
            maxlength="5"
            placeholder="Postal Code"
            value=""
            formControlName="zip"
            required
          />
          <mat-hint align="end">{{ postalCode.value.length }} / 5</mat-hint>
        </mat-form-field>
      </td>
    </tr>
  </table>
  <button type="submit" class="register" mat-button (click)="check()" color="primary">Save</button>
  <!-- <button type="submit" [disabled]="!registerForm.form.valid" class="register" mat-button (click)="check()" color="primary">Save</button> -->
</form>

Here's my ts file:

import { Component, OnInit } from '@angular/core'
import { LoginService } from '../login.service'
import { FormControl, Validators, FormGroup, FormBuilder } from '@angular/forms'

@Component({
  selector: 'app-profile',
  templateUrl: './profile.component.html',
  styleUrls: ['./profile.component.css'],
})
export class ProfileComponent implements OnInit {
  firstFormGroup: FormGroup
  profileInfo: Object[]

  constructor(private _formBuilder: FormBuilder, private _auth: LoginService) {}
  getInfo() {
    let value
    this._auth.profile({ username: 'evanlalo' }).subscribe((res) => {
      for (const item in res) {
        if (this.firstFormGroup.value.hasOwnProperty(item)) {
          value = res[item]
          console.log(value)
          this.firstFormGroup.patchValue({ item: value })
          console.log(item, res[item])
        }
      }
    })
  }

  ngOnInit() {
    this.firstFormGroup = this._formBuilder.group({
      company: new FormControl('', Validators.required),
      first_name: new FormControl('', Validators.required),
      last_name: new FormControl('', Validators.required),
      address: new FormControl('', Validators.required),
      city: new FormControl('', Validators.required),
      state: new FormControl('', Validators.required),
      zip: new FormControl('', Validators.required),
      email: new FormControl('', [Validators.required, Validators.email]),
    })

    this.getInfo()
  }
}

All of the keys match the form field names but it will not work if I use the item variable. The weird thing is that if I hard code the field name IE company, the field will be set.

Any help would be appreciated.

thanks,

Caro answered 8/8, 2018 at 22:26 Comment(0)
B
15

In your case patchValue syntax is wrong.

Correct syntax is,

this.firstFormGroup.patchValue({[item]: value});

use [item] instead of item

[item] it means dynamic keys added to formGroup

Birecree answered 9/8, 2018 at 5:31 Comment(6)
That didn't work for me. How is it supposed to know what key to patch? Also, why does it work if I specifically type the key IE. this.firstFormGroup.patchValue({ company: value}; as opposed to when I use the current key in the loop IE this.firstFormGroup.patchValue({ item: value });Caro
I have updated my answer, Try this solution. you will get rid out from your problem.Birecree
Worked like a charm, thanks! Do you know why your solution works and mine doesn't?Caro
You are using only 'item', it means you are adding hardcoded string not the dynamic key so, In the new ES2015 standard for JavaScript (formerly called ES6), objects can be created with computed keys: like [item]. it means you are using dynamic keys.Birecree
Thank you, it helped me a lot!Subdue
I was using a [Record<string, unknown>] to collect the fields which needed to be patched. After reading this, I switched to an interface of [key: string]: AnswerType` and the problem was fixed.Fibroma
S
4

If somehow any value part is undefined in patchValue, then also it did not work. for e.g. in below example if i want to patch a few columns like id, projectName etc. and somehow this.project.Id element is undefined (not filled from service) then also patchValue will not work without throwing any error.

 this.projectForm.patchValue({
      id: this.project.Id,
      ProjectName: this.project.ProjectName
 });
Semen answered 17/9, 2019 at 23:8 Comment(1)
Correct. I'm facing same issue. Any solution to this ?Donough
P
2

If you are working with Angular 9+ read this.

From Angular docs, it does make sense to use setValue({key: value}) instead of patchValue({key: value}) because setValue does not swallow errors. You will be thrown off if your object is nested/complex.

There are two ways to update the model value:

Use the setValue() method to set a new value for an individual control. The setValue() method strictly adheres to the structure of

the form group and replaces the entire value for the control.

Use the patchValue() method to replace any properties defined in the object that have changed in the form model.

The strict checks of the setValue() method help catch nesting errors in complex forms, while patchValue() fails silently on those errors.

Also you cannot use patchValue({[key]: value}); //no parenthesis

Purnell answered 28/9, 2020 at 0:22 Comment(0)
C
0

maybe, the control doesn't exist.

You may control it and register if it doesn't.

Then you shall be able to use patch, and I would recommend using patch over set.

if(!this.firstFormGroup.get('item')) {
  this.firstFormGroup.registerControl('item', value)
}
Catechist answered 8/6, 2022 at 14:43 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.