According to the HTML specification most attributes are defined as strings, however some can be interpreted as different types like booleans or numbers. [In the HTML standard](https://html.spec.whatwg.org/multipage/common-microsyntaxes.html#boolean-attributes), boolean attributes are considered `true` if they are present on a DOM node and `false` if they are omitted. Common examples of boolean attributes are `disabled` on interactive elements like `<button>` or `checked` on `<input type="checkbox">`. Another example of an attribute that is defined as a string, but interpreted as a different type is the `value` attribute of `<input type="number">` which logs a warning and ignores the value if it can't be parsed as a number.
Historically, authoring Angular inputs that match the native behavior in a type-safe way has been difficult for developers, because Angular interprets all static attributes as strings. While some recent TypeScript versions made this easier by allowing setters and getters to have different types, supporting this pattern still requires a lot of boilerplate and additional properties to be declared. For example, currently developers have to write something like this to have a `disabled` input that behaves like the native one:
```typescript
import {Directive, Input} from '@angular/core';
@Directive({selector: 'mat-checkbox'})
export class MatCheckbox {
@Input()
get disabled() {
return this._disabled;
}
set disabled(value: any) {
this._disabled = typeof value === 'boolean' ? value : (value != null && value !== 'false');
}
private _disabled = false;
}
```
This feature aims to address the issue by introducing a `transform` property on inputs. If an input has a `transform` function, any values set through the template will be passed through the function before being assigned to the directive instance. The example from above can be rewritten to the following:
```typescript
import {Directive, Input, booleanAttribute} from '@angular/core';
@Directive({selector: 'mat-checkbox'})
export class MatCheckbox {
@Input({transform: booleanAttribute}) disabled: boolean = false;
}
```
These changes also add the `booleanAttribute` and `numberAttribute` utilities to `@angular/core` since they're common enough to be useful for most projects.
Fixes#8968.
Fixes#14761.
PR Close#50420
This commit updates the minimum supported Node version across packages from 16.13.0 -> 16.14.0 to ensure compatibility with dependencies.
PR Close#49771
Previously, this PR cleaned up a bug introduced by #48679. However, since that PR needed to be rolled back, this PR now just checks in the test, to prevent that issue from re-occurring in the future.
PR Close#49693
This commit updates parts of the FW to be ES2022 complaint.
These changes are needed to fix the following problems problems with using properties before they are initialized.
Example
```ts
class Foo {
bar = this.buz;
constructor(private buz: unknown){}
}
```
PR Close#49559
This commit updates parts of the FW to be ES2022 complaint.
These changes are needed to fix the following problems problems with using properties before they are initialized.
Example
```ts
class Foo {
bar = this.buz;
constructor(private buz: unknown){}
}
```
PR Close#49332
The private util `isObservable` was actually just testing the same thing as`isSubscribable()`. As the implementation is closer to the function's name, let's only keep ``isSubscribable`.
PR Close#49295
BREAKING CHANGE: Node.js v14 support has been removed
Node.js v14 is planned to be End-of-Life on 2023-04-30. Angular will stop supporting Node.js v14 in Angular v16. Angular v16 will continue to officially support Node.js versions v16 and v18.
PR Close#49255
`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
Tests now always run with ESM 2020, while previously they ran with
ES2015 CommonJS UMD bundles.
Since ZoneJS does not support intercepting native `async/await` syntax,
the forms test needs to use the zone-compatible variant of
`jasmine_node_tests`. This variant downlevels the native `async/await`
syntax to generators that ZoneJS can intercept. All of this is done
using the dev-infra ESBuild `spec_bundle` rule.
PR Close#48521
Since we generate a `.mjs` file as entry-point for jasmine tests,
a couple of issues prevented the transitive dependencies from
bootstrap targets to be brought in (causing resolution errors):
1. The `_files` (previously `_esm2015`) targets are no longer needed,
and they also miss all the information on runfiles.
2. The aspect for computing linker mappings does not respect the
`bootstrap` attribute from the `spec_entrypoint` so we manually
add the extract ESM output targets (this rule works with the aspect
and forwards linker mappings).
PR Close#48521
For every `ts_library` target we expose a shorthand that grants
access to the JS files because `DefaultInfo` of a ts library
only exposes the `.d.ts` files.
We rename this away from `es2015` since in practice it's a much
higher target these days. Additionally we no longer use the devmode
output but rather use the prodmode output which has the explicit
`.mjs` output- compatible with ESM.
PR Close#48521
refactor(forms): make FormBuilder classes provided in root
This commit updates the FormBuilder classes to provide them in root
instead of using a deprecated pattern of providing a service in a specific
module using the `providedIn` syntax.
Closes#48237.
PR Close#48245
Fixes that the `AbstractControl` was mutating the validators arrays being passed into the constructor an helper methods like `setValidators`.
Fixes#47827.
PR Close#47830
[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
Fixes that the `AbstractControl` was mutating the validators arrays being passed into the constructor an helper methods like `setValidators`.
Fixes#47827.
PR Close#47830
This change aligns with the supported Node.js versions of the Angular CLI.
See: https://github.com/angular/angular-cli/pull/24026
BREAKING CHANGE: Angular no longer supports Node.js versions `14.[15-19].x` and `16.[10-12].x`. Current supported versions of Node.js are `14.20.x`, `16.13.x` and `18.10.x`.
PR Close#47730
Previously, `setDisabledState` was never called when attached if the control is enabled. This PR fixes the bug, and creates a configuration option to opt-out of the fix.
Fixes#35309.
BREAKING CHANGE: setDisabledState will always be called when a `ControlValueAccessor` is attached. You can opt-out with `FormsModule.withConfig` or `ReactiveFormsModule.withConfig`.
PR Close#47576
This commit exports existing utility functions to check for control instances:
isFormControl, isFormGroup, isFormRecord, isFormArray
Those are useful when implementing validators that use the specifics of one of those control types.
To narrow down the type to what it actually is, we can now use the util functions in validators:
```
export const myArrayValidator: ValidatorFn = (control) => {
if (!isFormArray(control)) { return null; }
// now you can use FormArray-specific members, e.g.:
if (control.controls.every(c => !!c.value) {
return { myerror: true }
} else { return null; }
}
```
PR Close#47718
Updated methods' description verbs. They are sometimes used with the assumption of the 'it' pronoun and sometimes not. For instance, the verb 'to construct' is used with 's' in one method description and not others. It is the case for other verbs as well. This is also remarkable in the description of the built-in methods of FormArray.
PR Close#47399
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
Type inference in cases involving `ControlConfig` was previously not working as desired. This was because the compiler was enforcing that `ControlConfig` is a *tuple* -- which is not always that easy to prove! By relaxing this constraint a bit, and just inferring from `ControlConfig` as an array, the type inference catches many more cases, and is generally more correct.
PR Close#47034
Users using the "disabled" property binding on reactive form controls would want to know how to dynamically update the disabled state of a form control when they get a console warning.
PR Close#47041
The new `FormRecord` entity introduced in Angular v14 does not have its builder method.
This commit adds it, allowing to write:
```
const fb = new FormBuilder();
fb.record({ a: 'one' });
```
This works for both the `FormBuilder` and the `NonNullableFormBuilder`
PR Close#46485
Replace `new Error()` in a forms Validators function with `RuntimeError`, for better tree-shakability. Also, improve the error messages, and add documentation.
PR Close#46537
Consider the case in which `FormBuilder` is used to construct a group with an optional field:
```
const controls = { name: fb.control('') };
const foo: FormGroup<{
name: FormControl<string | null>;
address?: FormControl<string | null>;
}> = fb.group<{
name: FormControl<string | null>;
address?: FormControl<string | null>;
}>(controls);
```
Today, with fully strict TypeScript settings, the above will not compile:
```
Types of property 'controls' are incompatible.
Type '{ name: FormControl<string | null>; address?: FormControl<FormGroup<SubFormControls> | null | undefined> | undefined; }' is not assignable to type '{ name: FormControl<string | null>; address?: FormGroup<SubFormControls> | undefined; }'.
```
Notice that the `fb.group(...)` is calculating the following type for address: `address?: FormControl<FormGroup<string|null>`. This is clearly wrong -- an extraneous `FormControl` has been added!
This is coming from the calculation of the result type of `fb.group(...)`. In the type definition, if we cannot detect the outer control type, [we assume it's just an unwrapped value, and automatically wrap it in `FormControl`](https://github.com/angular/angular/blob/14.0.0/packages/forms/src/form_builder.ts#L66).
Because the optional `{address?: FormControl<string|null>}` implicitly makes the RHS have type `FormControl<string|null>|undefined`, [the relevant condition is not satisfied](https://github.com/angular/angular/blob/14.0.0/packages/forms/src/form_builder.ts#L55). In particular, the condition expects just `FormGroup<T>`, not `FormGroup<T>|undefined`. So we assume `T` is a value type, and it gets wrapped with `FormControl`.
The solution is to add the cases where `undefined` is included in the union type when detecting which control `T` is (if any).
PR Close#46253
It is currently unclear which directive to use for FormRecord. This commit amends the docs to explicitly state that the group directives can and should be used with records.
PR Close#46235
DEPRECATED:
It is now deprecated to provide *both* `AbstractControlOption`s and an async validators argument to a FormControl. Previously, the async validators would just be silently dropped, resulting in a probably buggy forms. Now, the constructor call is deprecated, and Angular will print a warning in devmode.
DEPRECATED:
The `initialValueIsDefault` option has been deprecated and replaced with the otherwise-identical `nonNullable` option, for the sake of naming consistency.
In some places, the [@see][1] JSDoc tag was incorrectly used instead of
the [@link][2] inline tag, leading to warnings during doc generation and
the `@see` tags being ignored (and thus shown in the docs as is).
Replace the `@see` tags with the intended `@link` tags.
[1]: https://jsdoc.app/tags-see.html
[2]: https://jsdoc.app/tags-inline-link.html
PR Close#46040
* `FormRecord` jsdocs should now appear on a.io
* The `{@see foo#bar}` syntax previously did not work, and has been replace with backticks
PR Close#46023
Consider a typed group for storing contact information:
```
declare interface ContactControls {
name: FormControl<string|null>;
}
contactForm: FormGroup<ContactControls> = ...;
saveForm(form: FormGroup<ContactControls>) {
service.newContact(contactForm.value);
}
```
What should be the type of `newContact`? The answer, of course, is the value type:
```
declare interface Contact {
name: string|null;
}
class ContactService {
newContact(c: Contact) {}
}
```
This is quite redundant, and therefore, we should allow the value type to be generated automatically. We already have the helper types to do this -- we just need to document and export them. Then, this becomes possible:
```
class ContactService {
newContact(c: RawValue<FormGroup<ContactControls>>) {}
}
```
PR Close#45978
Previously, using `FormBuilder` with a union type would produce unions of *controls*:
```
// `foo` has type `FormControl<string>|FormControl<number>`.
const c = fb.nonNullable.group({foo: 'bar' as string | number});
```
This actually works in many cases, due to how extraordinarily powerful Typescript's distributive types are (e.g. `value` still has type `string|number`), but it is subtly incorrect. Here is a code example that exposes the reason the inference is incorrect. It exploits the fact that Typescript will not "un-distribute" a type, producing an obviously spurious error:
```
// fc gets an inferred distributive union type `FormControl<string> | FormControl<number>`
let fc = c.controls.foo;
// Error: Type 'FormControl<string | number>' is not assignable to type 'FormControl<string> | FormControl<number>'.
fc = new FormControl<string|number>('', {initialValueIsDefault: true});
```
Instead, we want the union to apply to the *values*:
```
// `foo` should have type `FormControl<string|number>`.
const c = fb.nonNullable.group({foo: 'bar' as string | number});
```
Essentially, we want to prevent Typescript from distributing the type. [As specified in the handbook](https://www.typescriptlang.org/docs/handbook/2/conditional-types.html#distributive-conditional-types):
> Typically, distributivity is the desired behavior. To avoid that behavior, you can surround each side of the extends keyword with square brackets.
This PR applies this suggestion to `FormBuilder`'s type inference.
Fixes#45912.
PR Close#45942
Based on early feedback, calling `fb.nonNullable.group(...)` continues to be clunky for a form with many such groups. Allowing `NonNullableFormBuilder` to be directly injected enables the following:
```
constructor(private fb: NonNullableFormBuilder) {}
```
PR Close#45904
With typed forms, all `FormControl`s are nullable by default, because they can be reset to `null`. This behavior is possible to change by passing the option `initialValueIsDefault: true`. However, in a large form, this is extremely cumbersome, as the option must be repeated over and over. Additionally, it is not possible to take full advantage of `FormBuilder`, since `FormBuilder.group` and `FormBuilder.array` will produce nullable controls.
This PR introduces a new accessor `FormBuilder.nonNullable`, which produces *non-nullable* controls. Specifically, any call to `.control` will produce controls with `{initialValueIsDefault: true}`, and calls to `.array` or `.group` that implicitly build inner controls will have the same effect.
```ts
let nfb = new FormBuilder().nonNullable;
let name = nfb.group({who: 'Alex'}); // FormGroup<{who: FormControl<string>}>
name.reset();
console.log(name); // {who: 'Alex'}
```
PR Close#45852
Speeds up the dev-turnaround by only bundling types when packaging. Currently
bundling occurs for all the `ng_module` targets in devmode.
This has various positive benefits:
* Avoidance of this rather slower operation in development
* Makes APF-built packages also handle types for `ts_library` targets consistently.
* Allows us to ensure APF entry-points have `d.ts` _always_ bundled (working with ESM
module resolution in TypeScript -- currently experimental)
* Allows us to remove the secondary `package.json` files from APF (maybe APF v14? - seems
low-impact). This would clean-up the APF even more and fix resolution issues (like in Vite)
PR Close#45405
Previously, the following code would fail to compile:
```
let form: FormGroup<{email: FormControl<string | null>}>;
form = fb.group({
email: ['', Validators.required]
});
```
This is because the compiler was unable to properly infer the inner type of `ControlConfig` arrays in some cases. The same issue applies to `FormArray` as well under certain circumstances.
This change cleans up the `FormBuilder` type signatures to always use the explicit Element type, and to catch `ControlConfig` types that might fall through.
PR Close#45684
As part of the typed forms RFC, we proposed the creation of a new FormRecord type, to support dynamic groups with homogenous values. This PR introduces FormRecord, as a subclass of FormGroup.
PR Close#45607
This PR strongly types the forms package by adding generics to AbstractControl classes as well as FormBuilder. This makes forms type-safe and null-safe, for both controls and values.
The design uses a "control-types" approach. In other words, the type parameter on FormGroup is an object containing controls, and the type parameter on FormArray is an array of controls.
Special thanks to Alex Rickabaugh and Andrew Kushnir for co-design & implementation, to Sonu Kapoor and Netanel Basal for illustrative prior art, and to Cédric Exbrayat for extensive testing and validation.
BREAKING CHANGE: Forms classes accept a generic.
Forms model classes now accept a generic type parameter. Untyped versions of these classes are available to opt-out of the new, stricter behavior.
PR Close#43834
in the validators documentation, the value for the formControl for both required and requiredTrue validators is an empty string. This is OK for required since it gives us an error. But I think if we set the value of formControl responsible for requiredTrue to something other than an empty string (e.g.: 'some value'), it would demonstrate the difference between required and requiredTrue better.
PR Close#45533
in the validators documentation, the value for the formControl for both required and requiredTrue validators is an empty string. This is OK for required since it gives us an error. But I think if we set the value of formControl responsible for requiredTrue to something other than an empty string (e.g.: 'some value'), it would demonstrate the difference between required and requiredTrue better.
PR Close#45533
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
There was a subtle bug involving the opt-out class for FormBuilder, which I discovered during the ongoing migration. The types must be structurally the same, because people pass around FormBuilders, in addition to passing around the controls they produce. This PR ensures FormBuilder and UntypedFormBuilder are assignable to each other.
PR Close#45421
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
Node.js v12 will become EOL on 2022-04-30. As a result, Angular CLI v14 will no longer support Node.js v12.
BREAKING CHANGE:
Support for Node.js v12 has been removed as it will become EOL on 2022-04-30. Please use Node.js v14.15 or later.
PR Close#45286
model.ts is currently extremely large. This is the first step in an attempt to refactor it to be more easily navigable and reviewable. This commit breaks up `model.ts` into the following new files:
* `model/abstract_model.ts`: The remainder of the model, including the `AbstractControl` base class and helper functions which are used throughout.
* `model/form_control.ts`: `FormControl`, `FormControlOptions`, and helpers, plus the constructor and untyped friends.
* `model/form_array.ts`: `FormArray` and untyped friends.
* `model/form_group.ts`: `FormGroup` and untyped friends.
This first phase is a purely mechanical code move. There is no new code at all, and no interfaces have been separated.
PR Close#45217
Currently, there is a freestanding `getRawValue` function which examines the type of the control. This is an issue for refactoring `model.ts` because it creates unnecessary dependencies between the `AbstractControl` classes. It is cleaner to simply add this method to the model hierarchy and call it directly, and will ease upcoming refactoring.
PR Close#45200
Currently, there is a freestanding `getRawValue` function which examines the type of the control. This is an issue for refactoring `model.ts` because it creates unnecessary dependencies between the `AbstractControl` classes. It is cleaner to simply add this method to the model hierarchy and call it directly, and will ease upcoming refactoring.
PR Close#45200
We had previously introduced an `AnyForUntypedForms` type alias. However, given our updated migration plan, we actually want to use aliases for the model classes themselves. This commit introduces these aliases, and adds them to the public API. It must be merged before the types, in order to migrate google3.
PR Close#45205
When an `NgModel` is created within a `form`, it receives an `NgControl` based on its `name`, but
the control doesn't get swapped out if the name changes. This can lead to problems if the `NgModel`
is part of an `ngFor`, because the name can change based on its position in the list and a new
control can be defined with the same name, leading us to having multiple directives pointing to
the same control. For example, if we start off with a list like :
```
[0, 1, 2]; -> [NgModel(0), NgModel(1), NgModel(2)]
```
Then we remove the second item:
```
[0, 2]; -> [NgModel(0), NgModel(2)]
```
And finally, if we decide to add an item to the end of the list, we'll already have a control for
index 2, causing the list to look like:
```
[0, 2, 3]; -> [NgModel(0), NgModel(2), NgModel(2)]
```
These changes fix the issue by removing the old control when the `name` of the directive changes.
Fixes#38465.
Fixes#37920.
PR Close#40459
This commit updates the `PatternValidator` class to inherit `AbstractValidatorDirective` to make it conistent with other validators.
Closes angular#42267
PR Close#44887
BREAKING CHANGE: Forms [email] input coercion
Forms [email] input value will be considered as true if it is defined with any value rather
than false and 'false'.
PR Close#42803
Form required validator should not reject objects that contain a length attribute set to zero.
Fixes#30718.
Co-authored-by: Dylan Hunn <dylhunn@gmail.com>
BREAKING CHANGE: objects with a length key set to zero will no longer validate as empty.
This is technically a breaking change, since objects with a key `length` and value `0` will no longer validate as empty. This is a very minor change, and any reliance on this behavior is probably a bug anyway.
PR Close#33729
This implementation change was originally proposed as part of Typed Forms, and will have major consequences for that project as described in the design doc. Submitting it separately will greatly simplify the risk of landing Typed Forms. This change should have no visible impact on normal users of FormControl.
See the Typed Forms design doc here: https://docs.google.com/document/d/1cWuBE-oo5WLtwkLFxbNTiaVQGNk8ipgbekZcKBeyxxo.
PR Close#44316
PR Close#44806
Currently, `ngModel` calls` setValue` after the `resolvedPromise` is resolved.
The promise is resolved _after_ the child template executes. The change detection
is run but `OnPush` views are not updated because they are not marked as dirty.
PR Close#44886
This new feature allows negative indices to wrap around from the back, just like ES2021 `Array.at`. In particular, the following methods accept negative indices, and behave like corresponding Array methods:
* `FormArray.at(index)`: behaves the same as `Array.at(index)`
* `FormArray.insert(index, control)`: behaves the same as `Array.splice(index, 0, control)`
* `FormArray.setControl(index, control)`: behaves the same as `Array.splice(index, 1, control)`
* `FormArray.removeAt(index, control)`: behaves the same as `Array.splice(index, 1)`
Previous work in #44746 and #44631 (by @amitbeck).
Issue #44642.
Co-authored-by: Amit Beckenstein <amitbeck@gmail.com>
PR Close#44848
This functionally dead code was originally introduced via pull request
were added to verify the fix, and the many comments on that issue after
it was closed indicate that it wasn't actually resolved.
In fact, setting `selectedIndex` does absolutely nothing here, since
the selected index is immediately overridden by setting the `value`
property. A working fix (with tests) for the IE/Safari bug is in pull
request #23784. Originally this dead code was removed as part of that PR,
but @AndrewKushnir recommended creating a separate PR for the cleanup.
PR Close#37614
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
This implementation change was originally proposed as part of Typed Forms, and will have major consequences for that project as described in the design doc. Submitting it separately will greatly simplify the risk of landing Typed Forms. This change should have no visible impact on normal users of FormControl.
See the Typed Forms design doc here: https://docs.google.com/document/d/1cWuBE-oo5WLtwkLFxbNTiaVQGNk8ipgbekZcKBeyxxo.
PR Close#44316
Runtime error codes in the Core, Common and Forms packages were not included into the `public-api` group reviews. This commit creates the necessary golden files to keep track of further changes in the runtime codes.
This is a followup from https://github.com/angular/angular/pull/44398#issuecomment-1006910976.
PR Close#44677
Modified email validator to inherit abstractValidator.
For every validato type different PR will be raised as discussed in #42378.
Closes#42267
PR Close#44545
This commit performs some refactoring of the AbstractControl-based classes to employ shared `RuntimeError` class and also updates the code to avoid duplication and improve minification.
PR Close#44398
To make our test output i.e. devmode output more aligned
with what we produce in the NPM packages, or to be more
aligned with what Angular applications will usually consume,
the devmode output is switched from ES5 to ES2015.
Additionally various tsconfigs (outside of Bazel) have been
updated to match with the other parts of the build. The rules
are:
ES2015 for test configurations, ES2020 for actual code that will
end up being shipped (this includes the IDE-only tsconfigs).
PR Close#44505
This commit refactors the code of the base validators class to make it compatible with the property renaming optimization. Currently the code makes an assumption that the field with a specified name (defined as a string) can be found on an object, but with property renaming optimization this is not correct.
PR Close#44500
Make the following fixes:
* When submitting the entire migration in a disabled state, I commented out more code than strictly required
* Responding to some final review comments caused two conditions to become flipped
* Always use explicit checks instead of boolean corecion
* Fix one missed any cast in a test case
PR Close#44540
I previously strengthened some weak types in #44370. One of these fixes exposed an incorrect call into `_reduceChildren` from `_reduceValue`. This was caught in google3 by a caller who was extending `FormGroup` and overriding these methods.
Special thanks to Bart G for catching this issue and suggesting a fix.
PR Close#44483
Allow a FormControl to be reset to its initial value. Provide this feature via a new option in a FormControlOptions interface, based on AbstractControlOptions.
Also, expose the default value as part of the public API. This is part of a feature that has been requested elsewhere (e.g. in #19747).
This was originally proposed as part of typed forms. As discussed in the GDE session (and after with akushnir/alxhub), it is likely better to just reuse the initial value rather than accepting an additional default.
It is desirable to land this separately in order to reduce the scope of the typed forms PR, and make it a types-only change.
Pertains to issue #13721.
PR Close#44434
It is possible to pass arguments to `FormBuilder` using four different formats: value-only, boxed value, control config, and value-array. Currently, these different methods are not well-tested, especially as they interact. This PR will add tests for the variety of different argument shapes.
This was originally inspired by typed forms: when `FormBuilder` becomes typed, all these argument shapes should just work, with correct inferred types.
PR Close#44452
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
It is desirable to land this separately to reduce the scope of the Typed Forms PR, by focusing it only on the new type parameters (rather than incidental strictness fixes).
PR Close#44370
As mentioned in the previous commit, integration tests will be declared
in subpackages of `//integration`. For these tests to still rely on the
NPM packages from `HEAD`, we need to update the visibility.
PR Close#44238
This reverts commit cdf50ff931.
Reverting as this needs a little more work on the documentation side, plus
the `export declare interface` syntax in `model.ts` might have unintended
side effects in g3.
This implementation change was originally proposed as part of Typed Forms, and will have major consequences for that project as described in the design doc. Submitting it separately will greatly simplify the risk of landing Typed Forms. This change should have no visible impact on normal users of FormControl.
See the Typed Forms design doc here: https://docs.google.com/document/d/1cWuBE-oo5WLtwkLFxbNTiaVQGNk8ipgbekZcKBeyxxo.
PR Close#44316
This commit updates the code of the `SelectMultipleControlValueAccessor` to:
- improve typings to make them more precise
- updates the note that refers to IE, but we still can not remove the branch since it's needed for Universal (that uses Domino)
PR Close#44261
Data members in AbstractControl should be eagerly
initialized to address issue/24571. This eliminates the need to
constantly check for truthiness and makes code much more readable.
More PRs to follow to address issue/24571.
PR Close#44292
This commit makes the `FormControlStatus` symbol available as a public API. The symbol itself
was intended to become a part of the public API, but due to the missing re-export, the symbol
remains private.
Fixes#44176.
PR Close#44183
This commit updates the code of the min/max and minlength/maxlength validator directives to inherit `ngOnChanges` hooks from the base class (the `AbstractValidatorDirective` one), rather than implementing the hooks on the child classes. This was needed to avoid issues with hooks inheritance in ViewEngine, but since it's deprecated, the code can be cleaned up.
PR Close#43945
Modified minlength and maxlength validator to inherit abstractValidator
For every validator type different PR will be raised as discussed in #42378.
Closes#42267
PR Close#43998
Modified minlength and maxlength validator to inherit abstractValidator
For every validator type different PR will be raised as discussed in #42378.
Closes#42267
PR Close#43835
RxJS 7 versions prior to 7.4.0 export ES5 code, whereas Angular
applications using RxJS 6 today use ES2015. This was fixed in RxJS 7.4.0
which exposes ES2015 entrypoints as well. This commit updates Angular's
peer dependencies to require the newer RxJS.
PR Close#43748
This commit updates the `node` engines range for all Angular
framework packages to:
* No longer support NodeJS v12 `< 12.20`. This is done because APF v13
uses package export patterns which are only supported as of v12.20.
https://nodejs.org/api/packages.html#packages_subpath_patterns.
* Allows for the latest v16 NodeJS versions. This matches with the CLI
which added NodeJS v16 support with https://github.com/angular/angular-cli/pull/21854.
We already limit this to `>= v16.10.0` in preparation to only
supporting the LTS minors of Node v16.
BREAKING CHANGE: NodeJS versions older than `v12.20.0` are no longer
supported due to the Angular packages using the NodeJS package exports
feature with subpath patterns.
PR Close#43740
With the changes to support APF v13 in the `ng_package` rule, we have
removed the ambiguous `entry_point` attribute. The attribute suggested
that it would be used for determining the primary entry-point input
file. This was not the case as the flat module output file is consulted
for bundling et at. The attribute has been renamed to match its
purposed (renamed to `primary_bundle_name`).
We no longer need to set that attribute because the primary bundle
name is (1) not of relevance for consumers and (2) the rule already
infers the bundle name properly from the Bazel package.
PR Close#43431
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
Adds support for TypeScript 4.4. High-level overview of the changes made in this PR:
* Bumps the various packages to `typescript@4.4.2` and `tslib@2.3.0`.
* The `useUnknownInCatchVariables` compiler option has been disabled so that we don't have to cast error objects explicitly everywhere.
* TS now passes in a third argument to the `__spreadArray` call inside child class constructors. I had to update a couple of places in the runtime and ngcc to be able to pick up the calls correctly.
* TS now generates code like `(0, foo)(arg1, arg2)` for imported function calls. I had to update a few of our tests to account for it. See https://github.com/microsoft/TypeScript/pull/44624.
* Our `ngtsc` test setup calls the private `matchFiles` function from TS. I had to update our usage, because a new parameter was added.
* There was one place where we were setting the readonly `hasTrailingComma` property. I updated the usage to pass in the value when constructing the object instead.
* Some browser types were updated which meant that I had to resolve some trivial type errors.
* The downlevel decorators tranform was running into an issue where the Closure synthetic comments were being emitted twice. I've worked around it by recreating the class declaration node instead of cloning it.
PR Close#43281
Currently the error message functions are defined as static methods on a class which means that as soon as one of them is used somewhere, all of them have to be retained. This isn't a problem at the moment, because all of them are behind `ngDevMode` checks, but it's error prone and it's easy to fix.
These changes move them out into functions so that they can be imported individually. It also has the advantage of allowing Webpack to minify the function names.
PR Close#43223
Specifically: narrow the type used for form statuses from string to a union of possible statuses. Change the API methods from any to use the new type.
This is a breaking change. However, as discussed in the PR, breakage seems minimal, and google3 has been prepped to land this.
Background: we uncovered these any typings in the course of design work for typed forms. They could be fixed in a non-breaking manner by piggybacking them on top of the new typed forms generics, but it would be much cleaner to fix them separately if possible.
BREAKING CHANGE:
A new type called `FormControlStatus` has been introduced, which is a union of all possible status strings for form controls. `AbstractControl.status` has been narrowed from `string` to `FormControlStatus`, and `statusChanges` has been narrowed from `Observable<any>` to `Observable<FormControlStatus>`. Most applications should consume the new types seamlessly. Any breakage caused by this change is likely due to one of the following two problems: (1) the app is comparing `AbstractControl.status` against a string which is not a valid status; or, (2) the app is using `statusChanges` events as if they were something other than strings.
PR Close#42952
We can't update the framework to rxjs7 until version 13, because it contains breaking changes, but we can allow users to opt into it since all of our code should be compatible.
These changes expand the allowed version range of rxjs and add an integration test to verify that we don't get compilation errors. Note that we also have a test that runs the AIO examples against rxjs 7 already (#42660).
Fixes#41897.
PR Close#42991
Several new functionalities are possible with this change: the most requested is that callers can now check whether a control has a required validator. Other uses include incrementally changing the validators set without doing an expensive operation to reset all validators.
Closes#13461.
PR Close#42838
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
In combination with the TS `noImplicitOverride` compatibility changes,
we also want to follow the best-practice of adding `override` to
members which are implemented as part of abstract classes. This
commit fixes all instances which will be flagged as part of the
custom `no-implicit-override-abstract` TSLint rule.
PR Close#42512
When a FormControl, FormArray, or FormGroup is first constructed, if an async validator is attached, the `statusChanges` observable should receive a message when the validator complete (i.e. pending -> valid/invalid). If the validator was provided as part of the constructor options, it was not fired at construction time, which is fixed in this PR.
Fixes#35309.
PR Close#42553
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
For quite a while it is an unspoken convention to add a trailing
new-line files within the Angular repository. This was never enforced
automatically, but has been frequently raised in pull requests through
manual review. This commit sets up a lint rule so that this is
"officially" enforced and doesn't require manual review.
PR Close#42478
Switches the repository to TypeScript 4.3 and the latest
version of tslib. This involves updating the peer dependency
ranges on `typescript` for the compiler CLI and for the Bazel
package. Tests for new TypeScript features have been added to
ensure compatibility with Angular's ngtsc compiler.
PR Close#42022