When producing a listener, the template pipeline does the following in separate phases:
1. Generates all the variables available within its scope.
2. Adds `restoreView` and `resetView` calls if there are any referenced to local variables (e.g. `@let` or local refs).
3. Optimizes away the variables that aren't used.
This means that we can end up in a situation where the references to the variables in the scope no longer exist, but we still enter and leave the view as if they're there which is unnecessary.
These changes add a simple optimization pass that looks specifically for the pattern of a `restoreView` followed by a `return resetView(expr)`. Furthermore, by changing the order of some optimizations, we're able to drop the `getCurrentView` variable as well.
Fixes#66286.
```ts
@Component(...)
class Outer {
constructor() {
@Component(...)
class Inner {}
}
}
```
previous behavior was that IVy transformation was only applied to `Inner`, thus breaking `Outer` transformation.
Prior to this change, binding to radio value was sensitive to the order in which `value` & `formField` where binding in the template.
The compiler change makes that order non-important.
fixes#66402
Error message links now point to the archived documentation site (v*.angular.dev)
so that referenced content matches the framework version in use.
See angular#44650
PR Close#66374
This completes the rename started in #66136. `[field]` is too generic of
a selector for the forms system to own, and likely to cause naming
collisions with existing components. Therefore it is being renamed to
`[formField]`
Reworks how we store arrow functions in the following ways:
1. Rather than the `storeCallback` and `getCallback` instructions, we generate a single `arrowFunction` instruction.
2. The `arrowFunction` instruction uses a factory to create a new instance of the function when a function is read for the first time.
3. We now keep arrow functions in listeners in line so that they have access to `$event`.
Adds support for using arrow functions in Angular expressions. They generally behave like JS arrow functions with the same access as other Angular expressions, but with the following limitations:
* We only support arrow functions with implicit returns, e.g. `(a) => a + 1` is allowed while `(a) => { return a + 1 }` is not.
* Pipes can't be used inside arrow functions, but they can be passed through to pipes.
To avoid recreating the functions in each change detection, the compiler applies a couple of optimizations:
* If an arrow function only references its own parameters, it is extracted into a top-level constant that is passed around to the different usage sites.
* If an arrow function has references to the template context, we store it on the current view and read the stored value later on.
Fixes#14129.
Updates the template type checker to support arrow functions. The main challenge was getting the current infrastructure not to rewrite references to arrow function parameters.
Previously, object literal keys in the TCB did not have source spans attached. This made it difficult for the Language Service to distinguish between keys and values, leading to incorrect completion contexts and diagnostic locations.
This commit ensures that source spans are properly attached to the keys in the TCB.
This will replace the `[field]` directive, since `[field]` is a very
generic name for signal forms to commandeer
refactor(forms): hook up `formField` directive in compiler
Hooks up the `formField` direcive to get the same treatment as the
`field` directive in the compiler.
apply updated formatting
This commit updates the DOM security schema and sanitization logic to properly recognize and sanitize `href` and `xlink:href` attributes on SVG `<script>` elements.
Since the `Field` directive manages binding `FieldState` properties to
the underlying form control automatically, the type checker prohibits
explicit bindings to the same properties to avoid conflicts. This proved
problematic in cases where developers wanted to bind these properties to
the inputs of other directives on form controls. Now the framework will
bind the field state properties to all matching directive inputs on
native controls.
Fix#65617
Sets up the compliance tests to target es2022 since that's the default in the CLI. Also updates all of the tests, primarily because the generated output for static properties has changed.
Back in #39323, I added a new `ThisReceiver` node to represent accesses done through `this` and I ended up making it inherit from `ImplicitReceiver`. The logic was that in most cases accessing through `this` was the same as the implicit access.
Over the years this has proven to not be a great idea, because no other AST nodes do this and one has to keep it in mind whenever dealing with `ImplicitReceiver`.
These changes remove the inheritance and update all of the usage sites accordingly.
PR #60455 improved error reporting for `@Component.imports` by scoping the diagnostic to an individual
element within the `imports` array, but this may introduce hard to track diagnostics when it ends
up being reported (far) away from the component itself.
This can be even more problematic when the diagnostic would end up being reported in a declaration file,
as happened in issue #65686; the declaration files of an imported library contained syntax that the
static interpreter did not support, hence the `@Component.imports` was rejected with a diagnostic reported
in the library's declaration file. This diagnostic isn't guaranteed to be reported (e.g. the CLI only
gathers Angular-specific diagnostics for Angular-compiled files, which excludes declaration files).
This commit changes the diagnostic location to ensure it is being reported within the `@Component.imports`
expression, in most cases retaining the desirable effect of #60455 while avoiding out-of-band diagnostics.
* Allow custom controls to make `pending` a required input
* Refactor test for `pending` input to be consistent with other control
properties
* Test that `pending` inputs are reset when the field binding changes
* Allow custom controls to make `dirty` a required input
* Refactor test for `dirty` input to be consistent with other control
properties
* Test that `dirty` inputs are reset when the field binding changes
* Allow custom controls to make `hidden` a required input
* Refactor test for `hidden` input to be consistent with other control
properties
* Test that `hidden` inputs are reset when the field binding changes
* Recognize directives with non signal-based models as valid custom controls
* Relax type checker to allow non signal-based models
The `FormValueControl` and `FormCheckboxControl` interfaces still
require a `model()`-input, however, a custom control need not implement
either interface to be bound by the `Field` directive.
All of the following examples can be used to define a custom control:
```ts
// Preferred: model()
class MyFormControl implements FormValueControl<string> {
readonly value: model.required<string>();
}
// Supported: input() + output()
class MyFormControl {
readonly value: input.required<string>();
readonly valueChange: output<string>();
}
// Supported: @Input() + @Output()
class MyFormControl {
@Input({required: true}) value!: string;
@Output() valueChange: new EventEmitter<string>();
}
```
The latter two may still choose to implement `FormUiControl` for other
properties, but again it is not required.
Fix#65478
We recently allowed users to have a dynamic input `type` with signal forms, but the logic that infers the value type falls back to `string` even though in theory it can be any of the other types.
These changes expand the inferred type to `string | number | boolean | Date | null` if we detect a dynamic `type` binding.
Currently when the signal debug name transform sees something like `const foo = signal(0);`, it transforms the signal into `signal(0, {...(ngDevMode ? { debugName: 'foo' } : {})})`. After minification this becomes `signal(0, {})` which will allocate memory for the empty object literal.
These changes rework the logic to produce `signal(0, ...(ngDevMode ? [{ debugName: 'foo' }] : []))` which will be fully tree shaken away to `signal(0)`.
This is necessary to exclude a race condition where the MutationObserver initialized by the instruction fired before the inputs are binded.
fixes#65678