- Add registerOnChange, _unregisterOnChange for value change callbacks
- Add registerOnDisabledChange, _unregisterOnDisabledChange for disabled callbacks
- Add disabled changes effect to notify registered callbacks
- Call onChange callbacks from updateValue with emitModelEvent flag
- Add CachingWeakMap utility for memoization
- Add wrapFieldTreeForSyncUpdates Proxy wrapper
- Intercept fieldTree().value.set() calls to sync parent immediately
- Cache wrapped trees and states to preserve identity
- Add ValueUpdateOptions type with onlySelf, emitEvent options
- Add parent notification on value changes via effect
- Add parent notification helpers: scheduleParentUpdate, notifyParentUnlessPending
- Propagate dirty/touched/pristine/untouched to parent
- Support onlySelf option to prevent parent propagation
- Add valueChanges EventEmitter that emits when source signal changes
- Add statusChanges EventEmitter that emits when status changes
- Set up effects to emit to observables
- Add reset() method with optional value parameter
- Support FormControlState unboxing ({value, disabled} format)
- Add isFormControlState helper function
This commit introduces `SignalFormControl`, a bridge implementation that allows Signal-based forms to interoperate with existing Reactive Forms infrastructure. It extends `AbstractControl` with standard methods and reactive observables while handling state propagation to parent containers.
Unlike a normal `signal()`, a `linkedSignal()` can be in an error state when
its computation fails. Currently, there's a bug where `linkedSignal.update`
does not account for this error state, and will pass the internal `ERRORED`
`Symbol` as the current value to the updater function.
This commit fixes the issue by having `update()` check and throw the error
instead of calling the updater function.
Enables specifying a custom browser URL for router links via a new input,
allowing navigation to use an explicit browser URL in navigation options.
Closes#66805
Updates the plugin factory to directly invoke the 'initialize' function from the
Angular Language Service bundle. This replaces manual proxying and lazy-loading
logic with direct delegation, unifying the instantiation process within the bundle.
Previous the router tree was an opt-in feature that required manual enablement in settings.
Now the router tree is enabled by default whenever the application supports it and routes are detected.
Adds `ChangeDetectionStrategy.Eager` as an explicit alias for `ChangeDetectionStrategy.Default`. This improves readability when contrasting with `OnPush`, clarifying that the component will be checked eagerly when traversal reaches it.
Compiler findings:
- The compiler resolves `ChangeDetectionStrategy` enum members by value in `resolveEnumValue` (see `packages/compiler-cli/src/ngtsc/annotations/common/src/evaluation.ts`).
- Since `Eager` has usage value `1` (same as `Default`), it is correctly interpreted during static analysis.
- At runtime, `defineComponent` (in `packages/core/src/render3/definition.ts`) checks `changeDetection === ChangeDetectionStrategy.OnPush` (0). Any other value, including `1` (Eager/Default), results in eager checking behavior (`onPush: false`).
This commit introduces a JSON schema for angularCompilerOptions in the
Angular Language Service extension. It provides validation and autocompletion
for Angular-specific options in tsconfig.json files.
Remove `setControlValue()` from `FieldState` and convert `controlValue` to a
`WritableSignal` whose setter implements the debounced syncing behavior
of `setControlValue()`.
This commit converts the typescript import in api.ts to a type-only import
and updates the plugin factory to utilize standard TypeScript server types.
Internal interfaces and specific service types are replaced with general
types to decouple the factory wrapper from internal implementations.
Refactors the `ɵɵcontrolCreate` and `ɵɵcontrol` instructions to delegate control logic to the forms package via new `ɵngControlCreate` and `ɵngControlUpdate` lifecycle hooks. Previously, the logic for binding form state to native elements and custom controls was hardcoded within `@angular/core`.
**Compiler Changes:**
- Introduces a new compilation phase `specializeControlProperties` (in `control_directives.ts`).
- This phase detects properties named `formField` and specializes them into `ControlCreate` and `Control` IR opcodes.
- These opcodes emit `ɵɵcontrolCreate` and `ɵɵcontrol` instructions, respectively.
**Runtime Changes:**
- `ɵɵcontrolCreate` acts as the creation phase. It locates the control directive and invokes its `ɵngControlCreate` method.
- `ɵɵcontrol` acts as the update phase, and invokes the control directive's `ɵngControlUpdate` method (if present).
- Introduces a `passThroughInput` configuration in `ControlFeature`. This specifies the input name (e.g., `formField`) that triggers the control. If the runtime detects that this input is bound to multiple targets (e.g., the `FormField` directive *and* the host component), the control is flagged as "pass-through". In this state, `ɵngControlCreate` returns a no-op update function, deferring responsibility to the other consumer (e.g., the component managing the field itself).
**Forms Changes:**
- `FormField` directive implements `ɵngControlCreate` and `ɵngControlUpdate`.
- Inside this hook, `FormField` determines the type of control it is attached to (Native, CVA, or Custom Signal Control) and delegates to the appropriate handler (`nativeControlCreate`, `cvaControlCreate`, or `customControlCreate`).
- Consolidates all form binding logic within `@angular/forms/signals`, enabling support for new `FormValueControl` and `FormCheckboxControl` interfaces.
- Reorganizes the codebase by moving `FormField` from `api/` to `directive/` and splitting the binding logic into semantic pieces:
- `control_native.ts`, `control_cva.ts`, and `control_custom.ts` contain the specific handlers for each control type.
- `native.ts` and `select.ts` provide helpers for native element discovery and select-specific synchronization.
- `bindings.ts` manages the tracking and application of property/attribute bindings.
Consolidating the standard schema support into `standard_schema.ts` will
cut down on unnecessary g3 patch changes whenever we change
`validation_errors.ts`.