Skip to the solution
EasyFrontend8 min read

Explain the difference between FormGroup.patchValue() and FormGroup.setValue().

832 views

The problem

Question presented to candidate: "An edit-profile page loads a user from the API and fills a FormGroup. Sometimes the API leaves out a field and the page crashes, sometimes it does not. Explain the difference between setValue() and patchValue(), and which one you would use here."

What a strong answer should cover:

  • setValue() requires the exact shape: every control key must be present, or it throws NG01002: Must supply a value for form control with name: '...'; an unknown key throws NG01001.
  • patchValue() accepts a partial object, updates only the keys it recognises and silently ignores the rest.
  • With typed forms (v14+), TypeScript already rejects a partial object passed to setValue(); the runtime check is the safety net for untyped data such as API responses.
  • Disabled controls still count: setValue needs their key too, and form.value omits them while getRawValue() includes them.
  • Both work recursively on nested groups and arrays, both fire valueChanges once for the group, and both accept { emitEvent: false }.
  • reset() is different again: it restores initial values for nonNullable controls and sets the rest to null.

Clarifying questions expected:

  • "Is the API response guaranteed to have every field, or should missing fields keep their current values?"
  • "Do we want the page to fail loudly if the response shape changes?"

Code / implementation expected: Yes β€” call both on the same typed FormGroup and show the error text and the resulting values.

  • forms

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

8 min read Β· 10 sections

Read the code

AngularpatchValue, setValue (partial and full) and reset on a typed FormGroup with a disabled control
import { Component, signal } from "@angular/core";
import { FormControl, FormGroup, ReactiveFormsModule } from "@angular/forms";

@Component({
  selector: "app-root",
  imports: [ReactiveFormsModule],
  template: `
    <form [formGroup]="profile">
      <input id="name" formControlName="name" />
      <input id="email" formControlName="email" />
      <input id="plan" formControlName="plan" />
    </form>
    <button id="patch" (click)="patch()">patchValue (name only)</button>
    <button id="set-partial" (click)="setPartial()">setValue (name only)</button>
    <button id="set-full" (click)="setFull()">setValue(all keys)</button>
    <button id="reset" (click)="reset()">reset()</button>
    <p id="out">{{ out() }}</p>
  `,
})
export class AppComponent {
  profile = new FormGroup({
    name: new FormControl("Ada", { nonNullable: true }),
    email: new FormControl<string | null>("ada@example.com"),
    plan: new FormControl({ value: "pro", disabled: true }, { nonNullable: true }),
  });
  out = signal(this.describe("initial"));

  describe(label: string) {
    return label + ": value=" + JSON.stringify(this.profile.value) + " raw=" + JSON.stringify(this.profile.getRawValue());
  }

  patch() {
    // Partial object: only the keys you pass are touched.
    this.profile.patchValue({ name: "Grace" });
    this.out.set(this.describe("patch"));
  }

  setPartial() {
    try {
      // The type checker rejects this call (email and plan are missing), so we cast to show the runtime check.
      (this.profile as FormGroup).setValue({ name: "Linus" });
    } catch (e) {
      this.out.set("setValue threw: " + (e as Error).message.split(". Find")[0]);
    }
  }

  setFull() {
    // Every key, including the disabled one, must be present.
    this.profile.setValue({ name: "Linus", email: null, plan: "free" });
    this.out.set(this.describe("set"));
  }

  reset() {
    this.profile.reset();
    this.out.set(this.describe("reset"));
  }
}

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 3 of 121 in Angular

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All Angular questions
Up nextEasy

What are template reference variables?

Continue