Add `childSignalProp` to `ReactiveNodeKind` in order to consolidate `ReactiveNodeKind` types and enable Client-Only Wiz to use it.
(cherry picked from commit ae6d8dae75)
Update platform-server to use Angular 's native `RuntimeError` class.
This aligns error throwing patterns in platform-server with other packages of the framework such as core, common, and platform-browser.
For URL and host errors, the error messages are configured to return only the raw dynamic URL when `ngDevMode` is false (in production) to aid in troubleshooting without bloating production bundles.
Add overloads for built-in validation error keys so callers get precise error payload types from getError.
This enables signal forms template patterns like:
```html
@if (login.getError('minLength'); as minLengthError) {
<div>Login should be {{ minLengthError.minLength }} characters</div>
}
```
(cherry picked from commit 45e8fb5d6c)
By default, the `FetchBackend` on SSR will limit the response body size to 10 MB.
If the response body exceeds this limit, an error will be thrown.
This default value can be configured by providing by setting the `maxResponseBodySize` in `provideServerRendering`.
This is to prevent DoS on the server when loading large files
(cherry picked from commit 2acca1165d)
Updates `DomElementSchemaRegistry` to strip `:svg:` and `:math:` namespace prefixes
from tag names before querying `SECURITY_SCHEMA` at compile-time. This allows SVG
and MathML attributes to correctly match their security contexts during compilation.
(cherry picked from commit 61a97f22e8)
The title property in Router type already requires that the return type of a resolved
title is a string. The type was looser here only because 'data' values are typed
as 'any'.
BREAKING CHANGE: The return type for `TitleStrategy.getResolvedTitleForRoute`
was previously 'any' while the actual return type could only be either `string`
or `undefined`. The return type now reflects the possible values correctly.
Code that reads the value may need to be adjusted.
(cherry picked from commit ad37f52c12)
`UNSAFE_IFRAME_ATTRS` in the `RuntimeErrorCode` enum is a `@deprecated`
alias of `UNSAFE_ATTRIBUTE_BINDING` (same value -910) with no usages
anywhere. Drop it along with the paired
`tslint:disable-next-line:no-duplicate-enum-values` suppression.
`RuntimeErrorCode` is re-exported as `ɵRuntimeErrorCode`, so the
enum's value set is not a stability commitment.
(cherry picked from commit 51b1db54ad)
This enables the use of the `experimentalWebMcpTool` option on signal forms and implicitly declares a WebMCP tool based on the form data model. This is an experiment inspirted by the WebMCP declarative forms API to see if Angular's framework-level knowledge of the form's declarative data model can produce higher quality WebMCP tools than the web standard can on its own with less effort from the developer.
Example:
```typescript
// main.ts
import {bootstrapApplication} from '@angular/platform-browser';
import {provideExperimentalWebMcpForms} from '@angular/forms';
import {MyComp} from './form';
bootstrapApplication(MyComp, {
providers: [
// Activate the feature.
provideExperimentalWebMcpForms(),
],
});
```
```typescript
// form.ts
import {Component, signal} from '@angular/core';
import {form} from '@angular/forms';
@Component({ /* ... */ })
export class MyComp {
private readonly f = form(signal({
firstName: '',
lastName: '',
}), {
// Implicitly creates a WebMCP tool named `createUser` which accepts a `firstName` and `lastName` as parameters.
experimentalWebMcpTool: {
name: 'createUser',
description: 'Creates a user with the given name.',
},
// Invokes the submit action when the agent calls the WebMCP tool.
submission: {
action: () => {
console.log('User clicked submit, or agent called the tool!');
},
},
});
// ...
}
```
WebMCP is still an experimental standard and going through frequent changes in the Chrome implementation and the standards process. As a result, we should be clear about the support status of this API and its overall stability guarantees.
(cherry picked from commit 38e26f0759)
In server-side rendering (SSR) setups, passing request URLs directly to the lower-level rendering APIs `renderModule` or `renderApplication` can expose applications to Server-Side Request Forgery (SSRF) or Host Header Injection attacks via absolute-form request URLs.
To mitigate these vulnerabilities at the framework layer, this commit introduces the `allowedHosts` option to `PlatformConfig` (supporting exact hostnames, wildcards like `*.example.com`, or `*` to allow all).
During platform initialization inside `createServerPlatform`, the hostname of the request `url` is validated against the `allowedHosts` list. If the hostname is not authorized, bootstrap immediately throws a host validation error, preventing unauthorized rendering and silent SSRF bypasses.
Closes#68436
(cherry picked from commit 60552a73e8)
This is an ergonomic wrapper around `declareWebMcpTool`, allowing a user to define multiple tools directly on an injector's providers, rather than needing to find an injection context.
Example:
```typescript
import {bootstrapApplication, provideWebMcpTools} from '@angular/core';
await bootstrapApplication(RootComp, {
providers: [
provideWebMcpTools([
{
name: 'hello',
description: 'Says hello',
inputSchema: {type: 'object', properties: {}},
execute: async () => ({content: [{type: 'text', text: 'Hello, World!'}]});
},
]),
],
});
```
The `execute` function is invoked in the injection context of the `Injector` it is provided to, meaning you can easily `inject` dependencies and invoke them.
This also works particularly well with route `providers` and `withExperimentalAutoCleanupInjectors`, registering the tools when the router is navigated to and then automatically unregistering them when navigating away. Note that `withExperimentalAutoCleanupInjectors` is required for unregistration to work.
```typescript
import {provideWebMcpTools} from '@angular/core';
import {provideRouter} from '@angular/router';
provideRouter(
[
{
path: '',
component: Home,
providers: [
provideWebMcpTools([
{
name: 'hello',
description: 'Says hello',
inputSchema: {type: 'object', properties: {}},
execute: async () => ({content: [{type: 'text', text: 'Hello, World!'}]}),
},
]),
],
},
],
withExperimentalAutoCleanupInjectors(),
);
```
This exports `declareWebMcpTool`, a mechanism for registering WebMCP tools and tying them to Angular's `Injector` lifecycle. This function immediately registers the given tool and automatically unregisters it once the associated `Injector` is destroyed.
This exports the function and all transitively reachable types *except* for JSON Schema types as there are quite a lot and we don't want to couple to this particular implementation will likely be obsoleted by built-in types as the standard develops. If users want to leverage those, they should add their own dependency on `@mcp-b/webmcp-types`.
- Added `minDate()` and `maxDate()` for validating constraints on `Date` inputs.
- `ReadonlyFieldState.min` and `.max` now return
`Signal<NonNullable<TValue>`. This ensures that `min` and `max` inputs
on custom controls can accept a reliable type (matching their value
type).
- Made the `TWrite` type parameter of `MetadataKey` contravariant to
properly indicate that it's writable.
- Added `LimitKey` as a convenience type for defining validation limit
metadata (e.g. `MAX_NUMBER`, `MIN_DATE`).
- Added `LimitSelectionKey` which can be used to bind a `LimitKey` with
value-specific aggregation logic, to a generic metadata key (e.g. use
`MAX_NUMBER` to aggregate numbers for `MAX`).
PR Close#68001
The `min` and `max` validation rules previously handled `string` values
to accommodate numbers bound to text inputs. However, this is no longer
necessary as the control binding itself handles the conversion.
This change removes string support from these rules, simplifying the
types to `number | null`. The validation logic has been updated to use
concrete checks (`value === null || Number.isNaN(value)`) to ensure safe
TypeScript narrowing.
Associated tests have been updated to:
- Remove string-specific validation checks.
- Add coverage for text input bindings.
- Add coverage for empty input handling (standard behavior where empty
sets model to null and skips validation).
BREAKING CHANGE: `min` and `max` validation rules no longer support
string values. Bound values must be numbers or null.
PR Close#68001
Introduce a highly decoupled FVC and CVA custom control reset mechanism, and implement the framework-wide automatic `transformedValue` and native controls clearing bridge for both new Signal Forms and legacy forms (Template-driven and Reactive).
1. Custom Control Reset Propagation (Bug #2):
- Establish agnostic custom control resetting via `FormFieldBindingOptions.reset` in `FormField`.
- Ensure that `FieldNode.reset()` unconditionally triggers `writeValue` updates on CVA custom controls.
- Protect against duplicate writes during subsequent change detection updates in `control_cva.ts` by verifying and tracking previous written values in the local bindings cache.
2. Unified Framework-wide FormControl Integration:
- Introduce a monorepo-wide private InjectionToken `ɵFORM_CONTROL_INTEGRATION` and `ɵFormControlIntegration` interface to act as the single, decoupled bridge for hooking up FVC parse errors and receiving control resets across both Signal and legacy forms architectures.
- Simplify Signal Forms: make `FormField` implements `ɵFormControlIntegration` directly, removing the intermediate context object and reducing DI boilerplate down to a clean `useExisting: FormField` provider. Triggers the `onReset` callback directly inside `FormField.reset()`.
- Upgrade Legacy Forms: `NG_CONTROL_INTEGRATION_PROVIDER` provides the renamed token. `NgControl` handles the event subscription internally (`set onReset(callback)`) to recursively listen to `control.events` (`FormResetEvent`) lazily only when assigned, resolving all `FormControl` swapping timing and lifecycle cleanup races automatically.
3. Automatic `transformedValue` and Native Controls Utility Clearing:
- Make `Parser.reset()` method required in the interface for a cleaner and non-defensive execution.
- Wire `transformedValue` into the new integration token `ɵFORM_CONTROL_INTEGRATION` to clear validation parsing states on resets.
- Lazily resets the UI-facing `rawValue` linked signal utilizing the original native `linkedSignal.set` callback (`originalSet`), correctly bypassing the UI-to-model parser loopback and preventing redundant model writes during `reset()`.
- Wire up Native Controls (`control_native.ts\Device`): Hook `parent.onReset` inside native element creation to automatically trigger the native `parser.reset()` and force DOM writes (`setNativeControlValue`) back down to the DOM input value during resets, ensuring native elements with pending parsing validation errors are successfully cleared and synced on form resets.
TAG=agy
CONV=8b4cee1e-2117-42a4-b242-c8ec7bf01752
The time has come.
Note: #67382 introduced a breaking change where you could notice some sublte timing change on how `value` is set when using `rxResource` or a `stream` on a `resource`
Introduce a new configuration option `unmatchedInputBehavior` to the `componentInputBinding` feature. This option allows users to configure the behavior when a component input is not matched by any key in the router data.
The available values are:
- 'alwaysUndefined': (Default) Always binds undefined to unmatched inputs.
- 'undefinedIfStale': Binds undefined only if the input was previously available in the router data for the active route in the outlet.
This feature addresses concerns raised in #63835 and #52946 regarding the retention of default values for inputs that were never targeted by the router, while still ensuring that stale data is cleared when a parameter is removed.
In order to raise an error on upload progress on the `FetchBackend`, we split `reportProgress` into 2 respective properties.
DEPRECATED: The `reportProgress` option is deprecated please use `reportUploadProgress` & `reportDownloadProgress` instead.
Using explicit single generic arguments with transforms (for example, input<boolean>(false, {transform: booleanAttribute})) previously failed overload resolution.
Before this fix, type-checking produced:
````
✘ [ERROR] TS2769: No overload matches this call.
Overload 1 of 5, '(initialValue: boolean, opts?: InputOptionsWithoutTransform<boolean> | undefined): InputSignal<boolean>', gave the following error.
Type '(value: unknown) => boolean' is not assignable to type 'undefined'.
Overload 2 of 5, '(initialValue: undefined, opts: InputOptionsWithoutTransform<boolean>): InputSignal<boolean | undefined>', gave the following error.
Argument of type 'true' is not assignable to parameter of type 'undefined'. [plugin angular-compiler]
```
This change adds specialized overloads for explicit read generics.
ex:
```
await injectAsync(() => import('./test_service'))
```
We'll be reusing the features that were already used by the router to support components lazy-loading.
The commit introduces a new function to assist users who want to lazy load services and use the DI system to create them.
Example:
```ts
import {injectAsync} from 'angular/core';
class MyCmp {
someSvc = injectAsync(() => import('..'));
async onClick() {
(await this.someSvc()).handleClick();
}
}
```
These changes introduce the new `@Service` decorator which is a more ergonomic alternative to `@Injectable`. The reason we're adding a new decorator is that `@Injectable` has been around since the beginning of Angular and it has a lot of baggage that adds unnecessary overhead for users that generally want to define a singleton service, available in their entire app. The key differences between `@Service` and `@Injectable` are:
1. `@Service` is `providedIn: 'root'` by default. You can opt into providing the service yourself by setting `autoProvided: false` on it.
2. `@Service` doesn't allow constructor-based injection, only the `inject` function.
3. `@Service` doesn't support the complex type signature of `@Injectable` (`useClass`, `useValue` etc.). Instead it supports a single `factory` function.
Example:
```ts
import {Service} from '@angular/core';
import {HttpClient} from '@angular/common/http';
import {AuthService} from './auth';
@Service()
export class PostService {
private readonly httpClient = inject(HttpClient);
private readonly authService = inject(AuthService);
getUserPosts() {
return this.httpClient.get('/api/posts/' + this.authService.userId);
}
}
```
Since angular@12181b9, zone stability
contributes to the PendingTasks. There is now a single source of truth for application stability
tracked in PendingTasks. This change makes protractor's whenStable compatible with zoneless.
The `Router` and `HttpClient` also contribute to stability using the
`PendingTasks` injectable. There will likely be more updates in the
future to have more features contribute to stableness in a zoneless
compatible way.
This update uses PendingTasks for stability by default when ZoneJS is not present or
can be enabled with an option when ZoneJS is present (but otherwise ignored with ZoneJS).
fixes#68180
In order for resources to allow caching in SSR context (eg in the TransferState), resource need to be able to set their value synchronously.
If the resource value is not set synchronously, the resource will be in in a "loading" state which is responsible for destroying the server-hydrated resolved DOM.
- Injected `NG_VALIDATORS` into `FormField` and exposed it via an internal getter.
- Created a `computed` signal in `cvaControlCreate` to run legacy validators and map into standard validation errors without generic `as any` type assertions.
- Intercepted `registerOnValidatorChange` to trigger updates even when the model value remains unchanged (e.g., going from `null` to `null`).
- Added integration tests to verify parse error propagation and reactivity.
PR Close#67943
The `ComponentFactory` has been removed from the public API in #68055.
This commit continues the cleanup and also removes `ModuleWithComponentFactories` from the public API.
This API was deprecated for a longtime, and was remove by #68055 from the public API.
We do have alternatives to this old API, so we can entirely remove it to spare some bytes
Adds a documentation page for the NG01002 runtime error thrown by
FormGroup and FormArray when setValue is called with a value that is
missing an entry for one or more registered controls.
The error code is also changed from positive (1002) to negative (-1002)
so that Angular appends a link to the error reference page in dev mode,
consistent with how other documented errors (e.g. NG01101, NG01203) are
handled.
This commit updates provideClientHydration to automatically enable incremental hydration by default. It also introduces a new withNoIncrementalHydration feature for opting out, adds conflict safety checks, and includes a schematic migration.
This is to align the shape of the method with `createComponent`
BREAKING CHANGE:The second arguement of appRef.bootstrap does not accept `any` anymore. Make sure the element you pass is not nullable.
fixes#67946
Those APIs date back to pre-ivy times and are long deprecated.
BREAKING CHANGE: `ComponentFactoryResolver` and `ComponentFactory` are no longer available. Pass the component class directly to APIs that previously required a factory, such as `ViewContainerRef.createComponent` or use the standalone `createComponent` function.
Implements the logic at the compiler level that will de-duplicate host directives and merge them together. It will also report if a conflict is detected during merging.
Those APIs date back to pre-ivy times and are long deprecated.
BREAKING CHANGE: `ComponentFactoryResolver` and `ComponentFactory` are no longer available. Pass the component class directly to APIs that previously required a factory, such as `ViewContainerRef.createComponent` or use the standalone `createComponentFunction`.
it was only optional to avoid a breaking change in a minor
BREAKING CHANGE: The `currentSnapshot` parameter in `CanMatchFn` and the `canMatch` method of the `CanMatch` interface is now required. While this was already the behavior of the Router at runtime, existing class implementations of `CanMatch` must now include the third argument to satisfy the interface.
PR Close#67452
This adds support for a `debounce` option to the `validateAsync` and `validateHttp` functions.
This allows developers to debounce the triggering of async validators to improve performance.
A `DebounceTimer` type was also added to `@angular/core` to represent the wait condition parameters uniformly.
Added a `getError(kind: string)` method to `FieldState` that returns the first validation error of a given kind, or `undefined` if no such error exists. This method is reactive and will re-evaluate when errors change.
Fixes#63905
Also updated public API goldens and added unit tests.