Use whenStable instead of manual change detection so integration tests exercise scheduled rendering. Await asynchronous callbacks and remove redundant timer waits to keep assertions within the test lifecycle.
Replaces the remaining hand-rolled deferred promise implementations
with the native `Promise.withResolvers()` API and removes the now
unused helper and import.
Follow-up to #69739.
The default change detection strategy is now OnPush.
BREAKING CHANGE: Component with undefined `changeDetection` property are now `OnPush` by default. Specify `changeDetection: ChangeDetectionStrategy.Eager` to keep the previous behavior.
Implement support for `FormUiComponent`s in both Reactive and Template-driven
forms. This allows components that use the new signal-based form control
architecture to be used seamlessly within existing Angular form paradigms.
Key changes:
- Integrated `ɵngControlCreate` and `ɵngControlUpdate` lifecycle hooks into
`NgModel`, `FormControlDirective`, and `FormControlName`.
- Implemented branching logic to choose between the traditional `ControlValueAccessor` (CVA) path and the new FVC path based on the host element's capabilities.
- Added comprehensive unit tests for FVC integration in both Reactive (`reactive_fvc.spec.ts`) and Template-driven (`template_fvc.spec.ts`) forms, covering:
- Value synchronization (model -> view and view -> model).
- Status synchronization (touched, dirty, valid, invalid, pending, required).
- Error propagation and `parseErrors` support.
- Fallback behavior to native DOM properties (disabled, required) when FVC inputs are missing.
- Graceful fallback to CVA when no FVC pattern is detected.
- Refined `NgModel` to correctly handle `required` validation via its existing `RequiredValidator` directive while supporting FVC for other properties.
Removes usages of zone-based helpers such as `fakeAsync` , `tick`
`waitForAsync` as part of the migration to zoneless tests.
Completes the transition to zoneless.
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 updates tests and examples only to prepare for zoneless by default.
These changes were identified and made as part of #63382. Anything that
failed gets `provideZoneChangeDetection` unless the fixes were easily
and quickly determined.
It also adds the zoneless provider to the `initTestEnvironment` calls
for tests in this repo to prevent regressions before #63382 is merged.
PR Close#63668
The `FormArrayDirective` will allow to have a `FormArray` as a top-level form object.
* `NgControlStatusGroup` directive will be applied to the `FormArrayDirective`
* `NgForm` will still create a `FormGroup`
Fixes angular#30264
BREAKING CHANGE: This new directive will conflict with existing FormArray directives or formArray inputs on the same element.
PR Close#55880
These helpers are often imported by various tests throughout the
repository, but the helpers aren't exported/exposed from the public
entry-point; even though they confusingly reside in there.
This commit fixes this, and moves the helpers into
`packages/private/testing`. This is a preparation for the `ts_project`
migration where we don't want to leverage deep imports between packages.
PR Close#61472
Adds the `markAllAsDirty` method to the `AbstractControl` class. This method will mark the control and all its
descendants as dirty.
I pretty much just duplicated the behaviour and tests of `markAllAsTouched`.
Fixes#55990
PR Close#58663
When a formControlName is used without a parent formGroup, an error is
logged in the console. Before this commit, there was no information
about which control had the issue. Now, it's reported and the
troubleshoot is much faster.
PR Close#55397
This commit introduces a new method to subscribe to on every `AbstractControl` subclass.
It allows to track value, pristine, touched and status changes on a given control.
Fixes#10887
PR Close#54579
A lot of our tests are wrapped in `{}` which serves no purpose, aside from increasing the nesting level and, in some cases, causing confusion. The braces appear to be a leftover from a time when all tests were wrapped in a `function main() {}`. The function declaration was removed in #21053, but the braces remained, presumably because it was easier to search&replace for `function main()`, but not to remove the braces at the same time.
PR Close#52239
Currently internally Angular has some customized tsconfig files, because we don't align with the tsconfig of the rest of g3. These changes enable `noImplicitReturns` and `noPropertyAccessFromIndexSignature` to align better with the internal config.
PR Close#51728
`setDisabledState` is supposed to be called whenever the disabled state of a control changes, including upon control creation. However, a longstanding bug caused the method to not fire when an *enabled* control was attached. This bug was fixed in v15.
This had a side effect: previously, it was possible to instantiate a reactive form control with `[attr.disabled]=true`, even though the the corresponding control was enabled in the model. (Note that the similar-looking property binding version `[disabled]=true` was always rejected, though.) This resulted in a mismatch between the model and the DOM. Now, because `setDisabledState` is always called, the value in the DOM will be immediately overwritten with the "correct" enabled value.
Users should instead disable the control directly in their model. (There are many ways to do this, such as using the `{value: 'foo', disabled: true}` constructor format, or immediately calling `FooControl.disable()` in `ngOnInit`.)
If this incompatibility is too breaking, you may also opt out using `FormsModule.withConfig` or `ReactiveFormsModule.withConfig` at the time you import it, via the `callSetDisabledState` option.
However, there is an exceptional case: radio buttons. Because Reactive Forms models the entire group of radio buttons as a single `FormControl`, there is no way to control the disabled state for individual radios, so they can no longer be configured as disabled.
In this PR, we have special cased radio buttons to ignore their first call to `setDisabledState` when in `callSetDisabledState: 'always'` mode. This preserves the old behavior.
PR Close#48864
Jasmine has deprecated the `expectationFailOutput` argument and replaced it by the `withContext()` method
Also removing all references to #24571 from the forms unit tests as the non null assertions are fine in the context.
PR Close#48894
[A Github issue](https://github.com/angular/angular/issues/43821) about an arcane-sounding Forms error is one of the repo's top-ten most visited pages. This converts the error to `RuntimeErrorCode` and adds a dedicated guide to explain how to solve it.
PR Close#47969
The forms `submit` event handlers have a `return false` to prevent form submissions from reloading the page, however this also prevents the browser behavior for forms with `method="dialog"`.
These changes add an exception since the `method="dialog"` doesn't refresh the page.
Fixes#47150.
PR Close#47308
Fixes a long-standing issue where swapping out the `FormGroup` and calling `disable` immediately afterwards doesn't actually disable the `ControlValueAccessor`.
Fixes#22556.
PR Close#43499
Close#44724
`DebugNode.triggerEventHandler()` should accept the `eventObj` as an
optional parameter. So the user don't have to write code like
```
elem.triggerEventHandler('click', null);
```
PR Close#45279
Modified required validator and checkbox validator to inherit abstractValidator.
For every validato type different PR will be raised as discussed in #42378.
Closes#42267
PR Close#44162
Currently, many of our unit tests are written to use heterogenous groups and arrays, and controls that accept heterogenous values. This PR will make the minimum possible alterations to prepare those usages, mainly by annotating them as untyped controls, etc.
This PR is *not* intended to test typed forms, merely to minimize the size of the upcoming PR. This will allow that PR to be focused on the actual features and tests, rather than boilerplate fixes.
PR Close#44451
This commit updates the logic of the `min` and `max` validators to allow
disabling them dynamically in case `null` is provided as a value. For example: `<input
type="number" [min]="minValue">`, when `minValue` might be set to `null` in a
component class. This should allow `min` and `max` validators to be used for dynamic forms.
Note: similar support was added to the `minLength` and `maxLength`
validators earlier (see #42565).
PR Close#42978
If the validator is bound to be `null` then no validation occurs and
attribute is not added to DOM.
For every validator type different PR will be raised as discussed in
https://github.com/angular/angular/pull/42378.
Closes#42267.
PR Close#42565
As previously discussed in pull/31070 and issues/30486, this would be useful because it is often desirable to apply styles to fields that are both `ng-invalid` and `ng-pristine` after the first attempt at form submission, but Angular does not provide any simple way to do this (although evidently Angularjs did). This will now be possible with a descendant selector such as `.ng-submitted .ng-invalid`.
In this implementation, the directive that sets control status classes on forms and formGroups has its set of statuses widened to include `ng-submitted`. Then, in the event that `is('submitted')` is invoked, the `submitted` property of the control container is returned iff it exists. This is preferred over checking whether the container is a `Form` or `FormGroup` directly to avoid reflecting on those classes.
Closes#30486.
PR Close#42132.
This reverts commit 00b1444d12, undoing the rollback of this change.
PR Close#42132
As previously discussed in pull/31070 and issues/30486, this would be useful because it is often desirable to apply styles to fields that are both `ng-invalid` and `ng-pristine` after the first attempt at form submission, but Angular does not provide any simple way to do this (although evidently Angularjs did). This will now be possible with a descendant selector such as `.ng-submitted .ng-invalid`.
In this implementation, the directive that sets control status classes on forms and formGroups has its set of statuses widened to include `ng-submitted`. Then, in the event that `is('submitted')` is invoked, the `submitted` property of the control container is returned iff it exists. This is preferred over checking whether the container is a `Form` or `FormGroup` directly to avoid reflecting on those classes.
Closes#30486.
PR Close#42132
Prior to this change the `min` and `max` validator directives would not
set the `min` and `max` attributes on the host element. The problem was
caused by the truthy check in host binding expression that was
calculated as `false` when `0` is used as a value. This commit updates
the logic to leverage nullish coalescing operator in these host binding
expressions, so `0` is treated as a valid value, thus the `min` and
`max` attributes are set correctly.
Partially closes#42267
PR Close#42412
We have some internal proxies for all of the Jasmine functions, as well as some other helpers. This code hasn't been touched in more than 5 years, it can lead to confusion and it isn't really necessary since the same can be achieved using Jasmine.
These changes remove most of the code and clean up our existing unit tests.
PR Close#42177
The Validator and AsyncValidator interfaces provide a callback, `registerOnValidatorChange(fn)`. `registerOnValidatorChange` is supposed to be fired at least once to register `fn` with the validator. `fn` is then called by the validator whenever its inputs change. This was previously not happening for FormGroup validators, and is now fixed.
PR Close#41971