Skip to main content

required()

🧭 API map​

I want to…Details
See every accepted call styleSignatures
See common and advanced usageUsage and behavior
Compare presence validatorsrequired versus notNil
Customize messagesMessage configuration
Understand reactive constraintsReactive behavior
Return to the complete catalogBuilt-in validators

πŸ“ Signatures​

required
required(message)
required(options)

This validator has no configurable constraint value. Its options customize the failure message, which may itself be reactive, and the reactive when condition.

πŸ“– Usage and behavior​

Requires a value to be present. It can be passed directly or called with message options:

const myForm = form({
name: field('', [required]),
surname: field('', [required('Enter your surname.')]),
});

It rejects null, undefined, '', and NaN. It does not reject empty arrays, sets, maps, or objects. Use minLength(1) when a collection must contain an item:

const myForm = form({
roles: field<string[]>([], [required, minLength(1)]),
});

A failure is { kind: 'required', message }. The validator contributes required() === true metadata to its node.

Boolean answers and acceptance​

Boolean behavior compared with Angular

Form Nodes required accepts both true and false. This matches Angular Reactive Forms' Validators.required for booleans, but differs from Angular Signal Forms' required, which rejects false.

Use requiredTrue when the value must be exactly true, such as accepting terms or giving consent. Use required for a yes/no question where either answer is valid.

This comparison is specific to booleans; the validators do not share every empty-value rule. Verified against Angular v22.1.6: Signal Forms emptiness and Reactive Forms validators.

Initialize a yes/no question with field<boolean>(null, [required]): null means unanswered, and either boolean is valid. These validators do not narrow the field's TypeScript value type after validation.

checkout-model.ts
import { field, form, notNil, required, requiredTrue } from '../../src/public-api';

const checkout = form({
wantsInvoice: field<boolean>(null, [required]),
acceptedTerms: field(false, [requiredTrue]),
reference: field<string>(null, [notNil]),
});

checkout.wantsInvoice(); // null
checkout.wantsInvoice.valid(); // false: no answer yet
checkout.wantsInvoice.set(false);
checkout.wantsInvoice(); // false
checkout.wantsInvoice.valid(); // true: "No" is an answer

checkout.acceptedTerms.valid(); // false: acceptance must be true
checkout.acceptedTerms.set(true);
checkout.acceptedTerms.valid(); // true

checkout.reference.set('');
checkout.reference(); // ''
checkout.reference.valid(); // true: notNil permits empty strings
checkout.valid(); // true

if (!checkout.valid() || checkout.wantsInvoice() !== false || checkout.reference() !== '') {
throw new Error('A negative answer and an empty reference should pass once the terms are accepted.');
}

checkout.resetToInitial();
if (checkout.valid() || !checkout.wantsInvoice.hasError('required')
|| !checkout.acceptedTerms.hasError('requiredTrue') || !checkout.reference.hasError('notNil')) {
throw new Error('Reset should restore the three distinct validation failures.');
}

checkout.wantsInvoice.required(); // true
checkout.acceptedTerms.required(); // true
checkout.reference.required(); // false: notNil has no HTML required constraint
if (!checkout.wantsInvoice.required() || !checkout.acceptedTerms.required() || checkout.reference.required()) {
throw new Error('Only presence and acceptance rules should contribute required metadata.');
}

A native checkbox receives the HTML required constraint only for requiredTrue, because HTML requires a required checkbox to be checked. The node's logical required() flag remains true for both validators. See control binding.

required versus notNil​

Use required when an empty string or NaN should count as missing. Use notNil when only null and undefined are forbidden:

ValuerequirednotNil
null, undefinedInvalidInvalid
'', NaNInvalidValid
false, true, 0ValidValid
Whitespace-only stringsValidValid
Empty arrays, sets, maps, or objectsValidValid

An active required rule contributes node.required() === true; notNil contributes no required metadata or native required constraint. This distinction still matters on boolean fields, even though both rules accept either boolean. Failures use different error kinds and message-catalog keys: required and notNil.

πŸ’¬ Message configuration​

Every failure has a default English message. Where supported, pass a string as the final argument or use an options object for a static or reactive message, as shown above.

A message function may read signals. Returning undefined continues through node, Angular provider, process-wide, and built-in message fallbacks. See Validator messages.

⚑ Reactive behavior​

The options object accepts a reactive when predicate. Signals read from its validator context are tracked; while it returns false, the rule contributes neither errors nor constraint metadata.

const requireCompanyName = signal(false);
const companyName = field('', [
required({ when: () => requireCompanyName() })
]);

Reactive constraint functions and message functions track the signals they read. When a resolved constraint becomes unavailable, validators that support optional constraint sources temporarily stop contributing their error and metadata.

The validator runs synchronously as part of its node's validator source. Disabled, readonly, and hidden nodes skip validation until they become interactive again.