Skip to the solution
MediumFrontend9 min read

What is the purpose of updateOn in Reactive Forms?

548 views

The problem

Question presented to candidate: "Our username field calls the server on every keystroke to check availability, and a large search form recomputes results while people are still typing. What is updateOn in reactive forms, and how would it help here?"

What a strong answer should cover:

  • updateOn decides when the view value is written to the model: 'change' (default, every input event), 'blur' (when the control loses focus) or 'submit' (when the parent form is submitted).
  • Writing to the model is what triggers validators (including async ones), valueChanges and the dirty flag, so delaying the write delays all of them.
  • Set it per control in the options object, or once on a FormGroup / FormArray, where children inherit it and can override.
  • Programmatic setValue / patchValue ignore updateOn; it only governs values coming from the UI.
  • Template-driven equivalents: [ngModelOptions]="{ updateOn: 'blur' }" per field, [ngFormOptions] for the whole form.
  • Trade-offs: blur hides errors until focus leaves; submit gives no live feedback, and with submit the control is never marked touched by blur.

Clarifying questions expected:

  • "Do users need live feedback while typing, for example a password-strength meter?"
  • "Is the cost the validation itself, or something subscribed to valueChanges?"

Code / implementation expected: Yes β€” three controls with different updateOn values, showing when each value and its validation change.

  • forms
  • performance

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

9 min read Β· 10 sections

Read the code

AngularThree controls with updateOn change, blur and submit, counting valueChanges for each
import { Component, signal } from "@angular/core";
import { FormControl, FormGroup, ReactiveFormsModule, Validators } from "@angular/forms";

@Component({
  selector: "app-root",
  imports: [ReactiveFormsModule],
  template: `
    <form [formGroup]="form" (ngSubmit)="submitted.set(submitted() + 1)">
      <input id="change" formControlName="onChange" />
      <input id="blur" formControlName="onBlur" />
      <input id="submit" formControlName="onSubmit" />
      <button id="go" type="submit">Submit</button>
    </form>
    <p id="out">{{ out() }}</p>
  `,
})
export class AppComponent {
  form = new FormGroup({
    // default: the model updates (and validators run) on every input event
    onChange: new FormControl("", { nonNullable: true, validators: Validators.minLength(3) }),
    // only when the input loses focus
    onBlur: new FormControl("", { nonNullable: true, validators: Validators.minLength(3), updateOn: "blur" }),
    // only when the parent form is submitted
    onSubmit: new FormControl("", { nonNullable: true, validators: Validators.minLength(3), updateOn: "submit" }),
  });
  events = { onChange: 0, onBlur: 0, onSubmit: 0 };
  submitted = signal(0);
  out = signal("");

  constructor() {
    for (const key of ["onChange", "onBlur", "onSubmit"] as const) {
      this.form.controls[key].valueChanges.subscribe(() => {
        this.events[key]++;
        this.snapshot();
      });
    }
    this.snapshot();
  }

  snapshot() {
    const c = this.form.controls;
    const show = (k: "onChange" | "onBlur" | "onSubmit") => k + "=" + JSON.stringify(c[k].value) + "(" + c[k].status + ", events " + this.events[k] + ")";
    this.out.set([show("onChange"), show("onBlur"), show("onSubmit")].join(" "));
  }
}

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 48 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 nextMedium

What are functional Route Guards, and how do they differ from class-based guards?

Continue