Skip to main content

FieldApi

State, value views, navigation, and operations available on a field node.

Import

import type { FieldApi } from '@ngblocks/form-nodes';

When to use it

Use for helpers that operate on field state and actions without accepting a node declaration. A field's $api additionally has the callable signal contract described by CallableNodeApi.

Declaration

type FieldApi<TValue, TParent extends AnyNode = AnyNode> = {
nodeType(): 'field';
onValueChange(callback: (value: TValue, node: FieldNode<TValue, TParent>) => void, options?: {
injector?: Injector;
debounce?: number;
}): () => void;
form: Signal<NearestForm<TParent> | null>;
root: Signal<IsUnknownNode<TParent> extends true ? NavigationRoot : RootNode<TParent>>;
parent: Signal<TParent | null>;
path: Signal<readonly string[]>;
keyInParent: Signal<NodeKeyInParent<TParent>>;
value: NodeValueSignal<TValue, TValue>;
asReadonly(): Signal<TValue>;
set(value: TValue): void;
update(updater: (value: TValue) => TValue): void;
debouncing: Signal<boolean>;
flush(): void;
focus(options?: FocusOptions): void;
patch(value: TValue): void;
reset(...args: [
] | [
value: TValue
]): void;
resetToInitial(): void;
validators: Signal<Validators<TValue>> & {
(options: {
resolve?: boolean;
}): Validators<TValue>;
};
setValidators(validators: ValidatorSource<TValue, FieldNode<TValue>>): void;
errors: NodeErrorsSignal<FieldNode<TValue, TParent>>;
allErrors: Signal<readonly ValidationErrorWithTargetNode<AnyNode>[]>;
valid: Signal<boolean>;
invalid: Signal<boolean>;
getError<TKind extends keyof ValidationErrorMap>(kind: TKind): (ValidationErrorWithTargetNode<FieldNode<TValue, TParent>> & ValidationErrorMap[TKind]) | undefined;
getError<TKind extends keyof ValidationErrorMap | (string & {})>(kind: TKind): (ValidationErrorWithTargetNode<FieldNode<TValue, TParent>> & CustomValidationError<TKind>) | undefined;
hasError(kind: keyof ValidationErrorMap | (string & {})): boolean;
hasValidator(validator: (context: any) => unknown, options?: {
resolve?: boolean;
}): boolean;
min: Signal<NonNullable<TValue> | null>;
max: Signal<NonNullable<TValue> | null>;
minLength: Signal<number | null>;
maxLength: Signal<number | null>;
pattern: Signal<readonly RegExp[]>;
required: Signal<boolean>;
pending: Signal<boolean>;
submitting: Signal<boolean>;
validationStatus: Signal<ValidationStatus>;
touched: Signal<boolean>;
untouched: Signal<boolean>;
markAsTouched(options?: {
skipDescendants?: boolean;
}): void;
markAsUntouched(): void;
dirty: Signal<boolean>;
pristine: Signal<boolean>;
markAsDirty(): void;
markAsPristine(): void;
disabled: Signal<boolean>;
disabledReasons: Signal<readonly DisabledReason[]>;
enabled: Signal<boolean>;
disable(message?: string): void;
enable(): void;
readonly: Signal<boolean>;
writable: Signal<boolean>;
markAsReadonly(): void;
markAsWritable(): void;
hidden: Signal<boolean>;
visible: Signal<boolean>;
hide(): void;
show(): void;
};

Type parameters

ParameterConstraintDefault
TValueUnconstrainedRequired
TParentAnyNodeAnyNode

Declared members

The declaration above also includes inherited contracts and overloads where applicable.

MemberMeaning
nodeTypeReturns the concrete primitive represented by this node.
onValueChangeSubscribes to future exposed value changes and returns an idempotent cancellation function. Runs untracked, respects equality and control debounce, and skips initial values. Multiple listeners coexist with the construction callback; subscriptions are not cloned. The explicit injector, otherwise the registration context, owns the listener. The node's current injector also ends the subscription on destruction and acts as the fallback owner. Binding and ancestor ownership follow the node when it is rebound or detached. Without an injector, observation still works and can be canceled manually. A positive debounce delays only this callback until that many milliseconds without another change. Omitted or zero stays synchronous. Cancellation drops pending delivery. Node values, validation, and interaction state are unaffected by the subscription delay.
formNearest explicit form() containing this field, or null when no form workflow owns it. A nested explicit form is the workflow owner instead of the complete structural root.
rootComplete structural root containing this field. A standalone or detached field returns itself. Use this signal when traversal must cross nested form workflow boundaries.
parentImmediate structural parent of this field, or null when it is a root or has been detached.
pathProperty and array-index segments from the complete root to this field. Root fields use [].
keyInParentProperty or array index under which this field is stored, or null when it is a root field.
valueExposed field value. The equal option may retain an earlier equivalent value independently of the latest committed write used by controls and reset.
asReadonlyReturns a stable, live readonly signal of the exposed value, with no node operations. Preserves configured equality and committed-value reads; pending control input remains pending. This does not mark the node readonly or prevent deep mutation of object values. The node and its $api return the same signal, and the method is safe to extract.
setAssigns a committed value immediately without marking the field dirty.
updateComputes and sets a complete value from the current exposed value without marking the field dirty.
debouncingWhether a control-originated value is waiting to be committed by this field's numeric, blur-based, or asynchronous debounce. Programmatic writes do not activate this signal.
flushImmediately commits the pending value.control(), ending its configured debounce. Has no observable effect when no control update is pending.
focusFocuses the first [formNode] control currently bound to this field in DOM order.
patchAssigns a committed value like set(). Available through $api for generic infrastructure; ordinary field updates use set().
resetClears touched and dirty state and cancels pending control input. Passing a value also replaces internally committed value; omitting it preserves that value even when equal retains an older exposed value. Controls reset to the internally committed value.
resetToInitialRestores the field's captured initial value and resets its interaction state.
validatorsCurrent normalized validators assigned directly to this field, in declaration order.
setValidatorsReplaces this field's validators and immediately validates the current exposed value.
errorsA signal containing the validation errors of this field itself.
allErrorsA signal containing the validation errors of this field and its descendants. Fields have no descendants, so this contains the same errors as errors().
validWhether this field has completed validation without errors. False while validity is unknown.
invalidWhether this field currently has at least one validation error.
getErrorReturns the first validation error of this field matching kind. Suggests registered error kinds while accepting any custom string.
hasErrorWhether this node's own errors contain the given kind. Does not search descendants. Suggests registered error kinds while accepting any custom string.
hasValidatorWhether the same validator function is directly registered on this node, including async validators. By default, does not run validators. Set resolve to true to inspect resolved leaf references.
minStrictest minimum value contributed by active numeric or date validators, or null when absent.
maxStrictest maximum value contributed by active numeric or date validators, or null when absent.
minLengthStrictest minimum length contributed by active length validators, or null when absent.
maxLengthStrictest maximum length contributed by active length validators, or null when absent.
patternEvery regular expression contributed by the field's active pattern validators.
requiredWhether an active required validator currently marks this field as required.
pendingWhether this field has one or more active asynchronous validation operations.
submittingWhether an ancestor form is currently running its submission action.
validationStatusCurrent validation phase: 'valid', 'invalid', or 'unknown'.
touchedWhether this field has been marked touched.
untouchedLogical inverse of touched().
markAsTouchedMarks this field as touched and commits its pending control value for every debounce strategy while it is interactive.
markAsUntouchedClears stored touched state, making touched() false and untouched() true.
dirtyWhether this field currently reports user-modified state.
pristineLogical inverse of dirty().
markAsDirtyMarks this field as dirty, making dirty() true and pristine() false while it is interactive.
markAsPristineClears stored dirty state, making dirty() false and pristine() true.
disabledWhether this field is effectively disabled by its own state or an ancestor reason.
disabledReasonsActive inherited and local causes of this field's disabled state.
enabledLogical inverse of disabled().
disableDisables this field, optionally recording a user-facing reason. Sets disabled() to true and enabled() to false.
enableClears local disabled state, including a static initial disabled option. Continuing reactive conditions and inherited reasons remain effective, so enabled() may stay false.
readonlyWhether this field is effectively readonly through its own state or an ancestor.
writableLogical inverse of readonly().
markAsReadonlyMarks this field readonly, making readonly() true and writable() false.
markAsWritableClears local readonly state, including a static initial readonly option. Reactive conditions and ancestor readonly state can still prevent the node from becoming writable.
hiddenWhether this field is effectively hidden through its own state or an ancestor.
visibleLogical inverse of hidden().
hideHides this field, making hidden() true and visible() false without changing its value.
showClears local hidden state, including a static initial hidden option. Reactive conditions and ancestor hidden state can still keep the node hidden.