DEV Community

Tejas Kadam
Tejas Kadam

Posted on

The cross-field form validators Angular doesn't ship (so I built them)

Third small package in a series I started a couple weeks back (rule-lite, then entitlement-lite). This one's about Angular Reactive Forms.

Angular ships plenty of single-field validators - required, min, pattern - but almost nothing for cross-field rules. The moment a form needs "end date can't be before start date," or "state is required only if country is US," or "no two line items can share the same SKU," teams either hand-roll a one-off group validator per form or reach for a much heavier form library.

So I made validators-lite. Three group/array-level validators, each returning a plain ValidatorFn:

const form = new FormGroup({
  start: new FormControl(''),
  end: new FormControl(''),
}, {
  validators: [dateRange('start', 'end')],
});

form.errors; // { dateRange: {...} } if end is before start
Enter fullscreen mode Exit fullscreen mode

conditionalRequired and uniqueInArray work the same way - conditionalRequired('country', 'state', c => c === 'US') marks state required only when the condition is true, and uniqueInArray() fails a FormArray when two entries have the same value (or the same field, for arrays of objects).

One thing worth calling out: it has no hard dependency on @angular/forms. The validators are typed structurally against a minimal AbstractControlLike interface (.value, .get()), so any real FormGroup or FormArray satisfies them without an adapter - and the package stays usable in tooling that doesn't have Angular resolvable at type-check time.

Repo: https://github.com/tejas821/validators-lite
npm: https://www.npmjs.com/package/validators-lite

If you've hand-rolled similar validators or have thoughts on the API, I'd like to hear it.

Top comments (0)