Validator

match

Value must equal a sibling control. The classic 'confirm password' validator — pass the sibling's name.

Live demo

confirm.errors: null

Usage

import { FormControl, FormGroup } from '@angular/forms';
import { WrValidators } from 'ngwr/validators';

const form = new FormGroup({
  password: new FormControl(''),
  confirm:  new FormControl('', [WrValidators.match('password')]),
});

Why ngwr provides this

Cross-field equality (password confirmation) is awkward with built-ins — every project ends up hand-writing the same group-level validator. This one reads the sibling control by name.

It cannot see a mismatch that was there from the start

A control runs its validators inside its own constructor, before it has been attached to a parent — so the sibling lookup finds nothing and this returns null, and joining the group does not re-run it. formControlName revalidates when it binds, so a form rendered through the reactive-forms directives corrects itself on its first change detection. The window is open for whatever reads validity FIRST — a route guard or resolver checking form.valid, a form built and submitted from a service, a unit test. Put matchFields on the group to close it and keep this one on the child for the per-field message; they use different error keys and do not conflict.

API

NameDescriptionTypeDefault
signatureFactory — call with the sibling control name.(name: string) => ValidatorFn
lookupLooks up the sibling via control.parent.get(name). Returns null when the parent or sibling is missing.
error keyOn mismatch: { match: { target: 'password' } }. There is no empty guard — a filled value against an empty one reports.{ match: { target } }
initial valuesCannot report a mismatch until something revalidates the control — a control runs its validators before it has a parent, so the sibling lookup finds nothing. formControlName revalidates when it binds; a guard or a service reading form.valid first does not. Put matchFields on the group to close that window.

See also