You're Invited:Meet the Socket Team at RSAC and BSidesSF 2026, March 23–26.RSVP
Socket
Book a DemoSign in
Socket

@angular/forms

Package Overview
Dependencies
Maintainers
2
Versions
1019
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@angular/forms - npm Package Compare versions

Comparing version
22.0.0-next.3
to
22.0.0-next.4
+35
-24
fesm2022/_validation_errors-chunk.mjs
/**
* @license Angular v22.0.0-next.3
* @license Angular v22.0.0-next.4
* (c) 2010-2026 Google LLC. https://angular.dev/

@@ -735,2 +735,4 @@ * License: MIT

this.node = node;
this.fieldTreeOf = this.fieldTreeOf.bind(this);
this.stateOf = this.stateOf.bind(this);
}

@@ -788,4 +790,8 @@ resolve(target) {

}] : []));
fieldTreeOf = p => this.resolve(p);
stateOf = p => this.resolve(p)();
fieldTreeOf(p) {
return this.resolve(p);
}
stateOf(p) {
return this.resolve(p)();
}
valueOf = p => {

@@ -1307,8 +1313,20 @@ const result = this.resolve(p)().value();

}
markAsTouched() {
markAsTouched(options) {
untracked(() => {
this.nodeState.markAsTouched();
this.markAsTouchedInternal(options);
this.flushSync();
});
}
markAsTouchedInternal(options) {
if (this.validationState.shouldSkipValidation()) {
return;
}
this.nodeState.markAsTouched();
if (options?.skipDescendants) {
return;
}
for (const child of this.structure.children()) {
child.markAsTouchedInternal();
}
}
markAsDirty() {

@@ -1623,15 +1641,7 @@ this.nodeState.markAsDirty();

}
node.markAsTouched();
const onInvalid = options?.onInvalid;
const ignoreValidators = options?.ignoreValidators ?? 'pending';
let shouldRunAction = true;
untracked(() => {
markAllAsTouched(node);
if (ignoreValidators === 'none') {
shouldRunAction = node.valid();
} else if (ignoreValidators === 'pending') {
shouldRunAction = !node.invalid();
}
});
const shouldRun = shouldRunAction(node, options?.ignoreValidators);
try {
if (shouldRunAction) {
if (shouldRun) {
node.submitState.selfSubmitting.set(true);

@@ -1652,10 +1662,11 @@ const errors = await untracked(() => action?.(field, detail));

}
function markAllAsTouched(node) {
if (node.validationState.shouldSkipValidation()) {
return;
function shouldRunAction(node, ignoreValidators) {
switch (ignoreValidators) {
case 'all':
return true;
case 'none':
return untracked(node.valid);
default:
return !untracked(node.invalid);
}
node.markAsTouched();
for (const child of node.structure.children()) {
markAllAsTouched(child);
}
}

@@ -1733,3 +1744,3 @@ function setSubmissionErrors(submittedField, errors) {

export { BasicFieldAdapter, CompatValidationError, DEBOUNCER, FieldNode, FieldNodeState, FieldNodeStructure, FieldPathNode, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MetadataKey, MetadataReducer, PATTERN, REQUIRED, addDefaultField, apply, applyEach, applyWhen, applyWhenValue, assertPathIsCurrent, calculateValidationSelfStatus, createManagedMetadataKey, createMetadataKey, extractNestedReactiveErrors, form, getInjectorFromOptions, metadata, normalizeFormArgs, schema, signalErrorsToValidationErrors, submit };
export { BasicFieldAdapter, CompatValidationError, DEBOUNCER, FieldNode, FieldNodeState, FieldNodeStructure, FieldPathNode, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MetadataKey, MetadataReducer, PATTERN, REQUIRED, addDefaultField, apply, applyEach, applyWhen, applyWhenValue, assertPathIsCurrent, calculateValidationSelfStatus, createManagedMetadataKey, createMetadataKey, extractNestedReactiveErrors, form, getInjectorFromOptions, isArray, isObject, metadata, normalizeFormArgs, schema, signalErrorsToValidationErrors, submit };
//# sourceMappingURL=_validation_errors-chunk.mjs.map
/**
* @license Angular v22.0.0-next.3
* @license Angular v22.0.0-next.4
* (c) 2010-2026 Google LLC. https://angular.dev/

@@ -7,3 +7,3 @@ * License: MIT

import { FieldNode, getInjectorFromOptions, FieldNodeState, FieldNodeStructure, calculateValidationSelfStatus, extractNestedReactiveErrors, BasicFieldAdapter, form, normalizeFormArgs, signalErrorsToValidationErrors } from './_validation_errors-chunk.mjs';
import { FieldNode, getInjectorFromOptions, FieldNodeState, FieldNodeStructure, calculateValidationSelfStatus, extractNestedReactiveErrors, BasicFieldAdapter, normalizeFormArgs, form, isArray, isObject, signalErrorsToValidationErrors } from './_validation_errors-chunk.mjs';
export { CompatValidationError } from './_validation_errors-chunk.mjs';

@@ -158,6 +158,4 @@ import { linkedSignal, untracked, runInInjectionContext, computed, signal, ɵRuntimeError as _RuntimeError, EventEmitter, inject, Injector, effect } from '@angular/core';

}] : []));
const TRUE_SIGNAL = computed(() => true, ...(ngDevMode ? [{
debugName: "TRUE_SIGNAL"
}] : []));
class CompatValidationState {
node;
syncValid;

@@ -171,3 +169,4 @@ errors;

}] : []));
constructor(options) {
constructor(node, options) {
this.node = node;
this.syncValid = getControlStatusSignal(options, c => c.status === 'VALID');

@@ -188,3 +187,5 @@ this.errors = getControlStatusSignal(options, extractNestedReactiveErrors);

rawAsyncErrors = EMPTY_ARRAY_SIGNAL;
shouldSkipValidation = TRUE_SIGNAL;
shouldSkipValidation = computed(() => this.node.hidden() || this.node.disabled() || this.node.readonly(), ...(ngDevMode ? [{
debugName: "shouldSkipValidation"
}] : []));
status = computed(() => {

@@ -228,3 +229,3 @@ return calculateValidationSelfStatus(this);

}
return new CompatValidationState(options);
return new CompatValidationState(node, options);
}

@@ -259,2 +260,75 @@ newChild(options) {

function extractValue(field, filter) {
return untracked(() => visitFieldTree(field, filter));
}
function visitFieldTree(field, filter) {
const state = field();
const value = state.value();
const matchingChildren = extractChildren(field, value, filter);
if (matchingChildren !== undefined || isContainerNode(field, value)) {
return matchingChildren;
}
if (matchesFilter(state, filter)) {
return value;
}
return undefined;
}
function isContainerNode(field, value) {
return (isArray(value) || isObject(value)) && Object.keys(value).some(k => isFieldTreeNode(field[k]));
}
function extractChildren(field, value, filter) {
if (isArray(value)) {
const record = field;
const arrayValue = value;
const result = new Array(arrayValue.length);
let hasMatch = false;
for (let i = 0; i < arrayValue.length; i++) {
const child = record[i];
const childResult = visitFieldTree(child, filter);
if (childResult !== undefined) {
hasMatch = true;
}
result[i] = childResult;
}
return hasMatch ? result : undefined;
}
if (isObject(value)) {
const record = field;
const objectValue = value;
const entries = Object.keys(objectValue).map(key => {
const child = record[key];
return isFieldTreeNode(child) ? [key, child] : undefined;
}).filter(isKeyedChild).map(([key, child]) => {
const childResult = visitFieldTree(child, filter);
return childResult !== undefined ? [key, childResult] : undefined;
}).filter(v => v !== undefined);
return entries.length ? Object.fromEntries(entries) : undefined;
}
return undefined;
}
function isFieldTreeNode(value) {
return typeof value === 'function';
}
function isKeyedChild(value) {
return value !== undefined;
}
function matchesFilter(state, filter) {
if (!filter) {
return true;
}
if (filter.dirty !== undefined && state.dirty() !== filter.dirty) {
return false;
}
if (filter.touched !== undefined && state.touched() !== filter.touched) {
return false;
}
if (filter.enabled !== undefined) {
const enabled = !state.disabled();
if (enabled !== filter.enabled) {
return false;
}
}
return true;
}
const NG_STATUS_CLASSES = {

@@ -664,3 +738,3 @@ 'ng-touched': ({

export { NG_STATUS_CLASSES, SignalFormControl, compatForm };
export { NG_STATUS_CLASSES, SignalFormControl, compatForm, extractValue };
//# sourceMappingURL=signals-compat.mjs.map
/**
* @license Angular v22.0.0-next.3
* @license Angular v22.0.0-next.4
* (c) 2010-2026 Google LLC. https://angular.dev/

@@ -8,7 +8,7 @@ * License: MIT

import * as i0 from '@angular/core';
import { InjectionToken, ɵisPromise as _isPromise, resource, linkedSignal, inject, ɵRuntimeError as _RuntimeError, untracked, input, computed, Renderer2, DestroyRef, Injector, ElementRef, signal, afterRenderEffect, effect, ɵformatRuntimeError as _formatRuntimeError, Directive } from '@angular/core';
import { InjectionToken, resource, ɵisPromise as _isPromise, linkedSignal, inject, ɵRuntimeError as _RuntimeError, untracked, input, computed, Renderer2, DestroyRef, Injector, ElementRef, signal, afterRenderEffect, effect, ɵformatRuntimeError as _formatRuntimeError, Directive } from '@angular/core';
import { ɵFORM_FIELD_PARSE_ERRORS as _FORM_FIELD_PARSE_ERRORS, Validators, ɵsetNativeDomProperty as _setNativeDomProperty, ɵisNativeFormElement as _isNativeFormElement, ɵisNumericFormElement as _isNumericFormElement, ɵisTextualFormElement as _isTextualFormElement, NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
import { assertPathIsCurrent, FieldPathNode, addDefaultField, metadata, createMetadataKey, MAX, MAX_LENGTH, MIN, MIN_LENGTH, PATTERN, REQUIRED, createManagedMetadataKey, DEBOUNCER, signalErrorsToValidationErrors, submit } from './_validation_errors-chunk.mjs';
export { MetadataKey, MetadataReducer, apply, applyEach, applyWhen, applyWhenValue, form, schema } from './_validation_errors-chunk.mjs';
import { httpResource } from '@angular/common/http';
import { Validators, NG_VALUE_ACCESSOR, NgControl } from '@angular/forms';
import '@angular/core/primitives/signals';

@@ -502,4 +502,2 @@

const FORM_FIELD_PARSE_ERRORS = new InjectionToken(typeof ngDevMode !== 'undefined' && ngDevMode ? 'FORM_FIELD_PARSE_ERRORS' : '');
function createParser(getValue, setValue, parse) {

@@ -533,3 +531,3 @@ const errors = linkedSignal({

const parser = createParser(value, value.set, parse);
const formFieldParseErrors = inject(FORM_FIELD_PARSE_ERRORS, {
const formFieldParseErrors = inject(_FORM_FIELD_PARSE_ERRORS, {
self: true,

@@ -662,15 +660,2 @@ optional: true

function isNativeFormElement(element) {
return element.tagName === 'INPUT' || element.tagName === 'SELECT' || element.tagName === 'TEXTAREA';
}
function isNumericFormElement(element) {
if (element.tagName !== 'INPUT') {
return false;
}
const type = element.type;
return type === 'date' || type === 'datetime-local' || type === 'month' || type === 'number' || type === 'range' || type === 'time' || type === 'week';
}
function isTextualFormElement(element) {
return element.tagName === 'INPUT' || element.tagName === 'TEXTAREA';
}
function getNativeControlValue(element, currentValue) {

@@ -758,28 +743,2 @@ let modelValue;

}
function setNativeDomProperty(renderer, element, name, value) {
switch (name) {
case 'name':
renderer.setAttribute(element, name, value);
break;
case 'disabled':
case 'readonly':
case 'required':
if (value) {
renderer.setAttribute(element, name, '');
} else {
renderer.removeAttribute(element, name);
}
break;
case 'max':
case 'min':
case 'minLength':
case 'maxLength':
if (value !== undefined) {
renderer.setAttribute(element, name, value.toString());
} else {
renderer.removeAttribute(element, name);
}
break;
}
}

@@ -807,3 +766,3 @@ function customControlCreate(host, parent) {

if (parent.elementAcceptsNativeProperty(name) && !host.customControlHasInput(name)) {
setNativeDomProperty(parent.renderer, parent.nativeFormElement, name, value);
_setNativeDomProperty(parent.renderer, parent.nativeFormElement, name, value);
}

@@ -833,3 +792,3 @@ }

} else if (!propertyWasSet && parent.elementAcceptsNativeProperty(name)) {
setNativeDomProperty(parent.renderer, parent.nativeFormElement, name, value);
_setNativeDomProperty(parent.renderer, parent.nativeFormElement, name, value);
}

@@ -910,3 +869,3 @@ }

if (parent.elementAcceptsNativeProperty(name)) {
setNativeDomProperty(parent.renderer, input, name, value);
_setNativeDomProperty(parent.renderer, input, name, value);
}

@@ -935,5 +894,5 @@ }

element = inject(ElementRef).nativeElement;
elementIsNativeFormElement = isNativeFormElement(this.element);
elementAcceptsNumericValues = isNumericFormElement(this.element);
elementAcceptsTextualValues = isTextualFormElement(this.element);
elementIsNativeFormElement = _isNativeFormElement(this.element);
elementAcceptsNumericValues = _isNumericFormElement(this.element);
elementAcceptsTextualValues = _isTextualFormElement(this.element);
nativeFormElement = this.elementIsNativeFormElement ? this.element : undefined;

@@ -1063,3 +1022,3 @@ focuser = options => this.element.focus(options);

minVersion: "12.0.0",
version: "22.0.0-next.3",
version: "22.0.0-next.4",
ngImport: i0,

@@ -1072,3 +1031,3 @@ type: FormField,

minVersion: "17.1.0",
version: "22.0.0-next.3",
version: "22.0.0-next.4",
type: FormField,

@@ -1093,3 +1052,3 @@ isStandalone: true,

}, {
provide: FORM_FIELD_PARSE_ERRORS,
provide: _FORM_FIELD_PARSE_ERRORS,
useFactory: () => inject(FormField).parseErrorsSource

@@ -1106,3 +1065,3 @@ }],

minVersion: "12.0.0",
version: "22.0.0-next.3",
version: "22.0.0-next.4",
ngImport: i0,

@@ -1122,3 +1081,3 @@ type: FormField,

}, {
provide: FORM_FIELD_PARSE_ERRORS,
provide: _FORM_FIELD_PARSE_ERRORS,
useFactory: () => inject(FormField).parseErrorsSource

@@ -1153,3 +1112,3 @@ }]

minVersion: "12.0.0",
version: "22.0.0-next.3",
version: "22.0.0-next.4",
ngImport: i0,

@@ -1162,3 +1121,3 @@ type: FormRoot,

minVersion: "17.1.0",
version: "22.0.0-next.3",
version: "22.0.0-next.4",
type: FormRoot,

@@ -1189,3 +1148,3 @@ isStandalone: true,

minVersion: "12.0.0",
version: "22.0.0-next.3",
version: "22.0.0-next.4",
ngImport: i0,

@@ -1192,0 +1151,0 @@ type: FormRoot,

{
"name": "@angular/forms",
"version": "22.0.0-next.3",
"version": "22.0.0-next.4",
"description": "Angular - directives and services for creating forms",

@@ -15,5 +15,5 @@ "author": "angular",

"peerDependencies": {
"@angular/core": "22.0.0-next.3",
"@angular/common": "22.0.0-next.3",
"@angular/platform-browser": "22.0.0-next.3",
"@angular/core": "22.0.0-next.4",
"@angular/common": "22.0.0-next.4",
"@angular/platform-browser": "22.0.0-next.4",
"rxjs": "^6.5.3 || ^7.4.0"

@@ -20,0 +20,0 @@ },

/**
* @license Angular v22.0.0-next.3
* @license Angular v22.0.0-next.4
* (c) 2010-2026 Google LLC. https://angular.dev/

@@ -116,2 +116,60 @@ * License: MIT

/**
* Type utility that recursively unwraps the value type of a `FieldTree`.
*
* If the value type contains `AbstractControl` instances (common in compat mode),
* they are replaced with their underlying value types.
*/
type RawValue<T> = T extends AbstractControl<infer TValue, any> ? TValue : T extends (infer U)[] ? RawValue<U>[] : T extends object ? {
[K in keyof T]: RawValue<T[K]>;
} : T;
/**
* A type that recursively makes all properties of T optional.
* Used for the result of `extractValue` when filtering is applied.
* @experimental 21.2.0
*/
type DeepPartial<T> = (T extends (infer U)[] ? DeepPartial<U>[] : T extends object ? {
[K in keyof T]?: DeepPartial<T[K]>;
} : T) | undefined;
/**
* Criteria that determine whether a field should be included in the extraction.
*
* Each property is optional; when provided, the field must match the specified state.
*
* @category interop
* @experimental 21.2.0
*/
interface ExtractFilter {
readonly dirty?: boolean;
readonly touched?: boolean;
readonly enabled?: boolean;
}
/**
* Utility to unwrap a {@link FieldTree} into its underlying raw value.
*
* This function is recursive, so if the field tree represents an object or an array,
* the result will be an object or an array of the raw values of its children.
*
* @param field The field tree to extract the value from.
* @returns The raw value of the field tree.
*
* @category interop
* @experimental 21.2.0
*/
declare function extractValue<T>(field: FieldTree<T>): RawValue<T>;
/**
* Utility to unwrap a {@link FieldTree} into its underlying raw value.
*
* This function is recursive, so if the field tree represents an object or an array,
* the result will be an object or an array of the raw values of its children.
*
* @param field The field tree to extract the value from.
* @param filter Criteria to include only fields matching certain state (dirty, touched, enabled).
* @returns A partial value containing only the fields matching the filter, or `undefined` if none match.
*
* @category interop
* @experimental 21.2.0
*/
declare function extractValue<T>(field: FieldTree<T>, filter: ExtractFilter): DeepPartial<RawValue<T>>;
/**
* An error used for compat errors.

@@ -266,3 +324,3 @@ *

export { CompatValidationError, NG_STATUS_CLASSES, SignalFormControl, compatForm };
export { CompatValidationError, NG_STATUS_CLASSES, SignalFormControl, compatForm, extractValue };
export type { CompatFormOptions };
/**
* @license Angular v22.0.0-next.3
* @license Angular v22.0.0-next.4
* (c) 2010-2026 Google LLC. https://angular.dev/

@@ -10,3 +10,3 @@ * License: MIT

import { PathKind, SchemaPath, SchemaPathRules, LogicFn, OneOrMany, ValidationError, FieldValidator, FieldContext, TreeValidationResult, TreeValidator, WithOptionalFieldTree, DisabledReason, Debouncer, FieldTree } from './_structure-chunk.js';
export { AsyncValidationResult, BaseNgValidationError, ChildFieldContext, CompatFieldState, CompatSchemaPath, EmailValidationError, FORM_FIELD, Field, FieldState, FieldStateByMode, FormField, FormFieldBinding, FormFieldBindingOptions, FormOptions, FormSubmitOptions, IgnoreUnknownProperties, ItemFieldContext, ItemType, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MaxLengthValidationError, MaxValidationError, MaybeFieldTree, MaybeSchemaPathTree, MetadataKey, MetadataReducer, MetadataSetterType, MinLengthValidationError, MinValidationError, NativeInputParseError, NgValidationError, PATTERN, PatternValidationError, REQUIRED, ReadonlyArrayLike, ReadonlyCompatFieldState, ReadonlyFieldState, ReadonlyFieldTree, RemoveStringIndexUnknownKey, RequiredValidationError, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPathTree, SignalFormsConfig, StandardSchemaValidationError, Subfields, ValidationErrorOptions, ValidationResult, ValidationSuccess, Validator, WithField, WithFieldTree, WithOptionalField, WithoutField, WithoutFieldTree, apply, applyEach, applyWhen, applyWhenValue, createManagedMetadataKey, createMetadataKey, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit, validateStandardSchema, ɵNgFieldDirective } from './_structure-chunk.js';
export { AsyncValidationResult, BaseNgValidationError, ChildFieldContext, CompatFieldState, CompatSchemaPath, EmailValidationError, FORM_FIELD, Field, FieldState, FieldStateByMode, FormField, FormFieldBinding, FormFieldBindingOptions, FormOptions, FormSubmitOptions, IgnoreUnknownProperties, ItemFieldContext, ItemType, MAX, MAX_LENGTH, MIN, MIN_LENGTH, MarkAsTouchedOptions, MaxLengthValidationError, MaxValidationError, MaybeFieldTree, MaybeSchemaPathTree, MetadataKey, MetadataReducer, MetadataSetterType, MinLengthValidationError, MinValidationError, NativeInputParseError, NgValidationError, PATTERN, PatternValidationError, REQUIRED, ReadonlyArrayLike, ReadonlyCompatFieldState, ReadonlyFieldState, ReadonlyFieldTree, RemoveStringIndexUnknownKey, RequiredValidationError, RootFieldContext, Schema, SchemaFn, SchemaOrSchemaFn, SchemaPathTree, SignalFormsConfig, StandardSchemaValidationError, Subfields, ValidationErrorOptions, ValidationResult, ValidationSuccess, Validator, WithFieldTree, WithoutFieldTree, apply, applyEach, applyWhen, applyWhenValue, createManagedMetadataKey, createMetadataKey, emailError, form, maxError, maxLengthError, metadata, minError, minLengthError, patternError, provideSignalFormsConfig, requiredError, schema, standardSchemaError, submit, validateStandardSchema, ɵNgFieldDirective } from './_structure-chunk.js';
import { HttpResourceRequest, HttpResourceOptions } from '@angular/common/http';

@@ -13,0 +13,0 @@ import '@angular/forms';

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is too big to display