This commit introduces a new Input property called
`ngFormOptions` to the `NgForm` directive. You can use it
to set default `updateOn` values for all the form's child
controls. This default will be used unless the child has
already explicitly set its own `updateOn` value in
`ngModelOptions`.
Potential values: `change` | `blur` | `submit`
```html
<form [ngFormOptions]="{updateOn: blur}">
<input name="one" ngModel> <!-- will update on blur-->
</form>
```
For more context, see [#18577](https://github.com/angular/angular/pull/18577).
toString() from DefaultIterableDiffer is only used in tests and should not
be part of the production code. toString() methods from differs add
~ 0.3KB (min+gzip) to the production bundle size.
This commit introduces a new option to template-driven forms that
improves performance by delaying form control updates until the
"blur" or "submit" event. To use it, set the `updateOn` property
in `ngModelOptions`.
```html
<input ngModel [ngModelOptions]="{updateOn: blur}">
```
Like in AngularJS, setting `updateOn` to `blur` or `submit` will
delay the update of the value as well as the validation status.
Updating value and validity together keeps the system easy to reason
about, as the two will always be in sync. It's also worth noting
that the value/validation pipeline does still run when the form is
initialized (in order to support initial values).
Upcoming PRs will address:
* Support for setting group-level `updateOn` in template-driven forms
* Option for skipping initial validation run or more global error
display configuration
* Better support of reactive validation strategies
See more context in #18408, #18514, and the [design doc](https://docs.google.com/document/d/1dlJjRXYeuHRygryK0XoFrZNqW86jH4wobftCFyYa1PA/edit#heading=h.r6gn0i8f19wz).
BREAKING CHANGE
It is no longer possible to declare classes in this format.
```
Component({...}).
Class({
constructor: function() {...}
})
```
This format would only work with JIT and with ES5. This mode doesn’t
allow build tools like Webpack to process and optimize the code, which
results in prohibitively large bundles. We are removing this API
because we are trying to ensure that everyone is on the fast path by
default, and it is not possible to get on the fast path using the ES5
DSL. The replacement is to use TypeScript and `@Decorator` format.
```
@Component({...})
class {
constructor() {...}
}
```
This commit adds support for setting default `updateOn` values
in `FormGroups` and `FormArrays`. If you set `updateOn` to
’blur’` at the group level, all child controls will default to `’blur’`,
unless the child has explicitly specified a different `updateOn` value.
```
const c = new FormGroup({
one: new FormControl()
}, {updateOn: blur});
```
It's worth noting that parent groups will always update their value and
validity immediately upon value/validity updates from children. In other
words, if a group is set to update on blur and its children are individually
set to update on change, the group will still update on change with its
children; its default value will simply not be used.
This change allows ReflectiveInjector to be tree shaken resulting
in not needed Reflect polyfil and smaller bundles.
Code savings for HelloWorld using Closure:
Reflective: bundle.js: 105,864(34,190 gzip)
Static: bundle.js: 154,889(33,555 gzip)
645( 2%)
BREAKING CHANGE:
`platformXXXX()` no longer accepts providers which depend on reflection.
Specifically the method signature when from `Provider[]` to
`StaticProvider[]`.
Example:
Before:
```
[
MyClass,
{provide: ClassA, useClass: SubClassA}
]
```
After:
```
[
{provide: MyClass, deps: [Dep1,...]},
{provide: ClassA, useClass: SubClassA, deps: [Dep1,...]}
]
```
NOTE: This only applies to platform creation and providers for the JIT
compiler. It does not apply to `@Compotent` or `@NgModule` provides
declarations.
Benchpress note: Previously Benchpress also supported reflective
provides, which now require static providers.
DEPRECATION:
- `ReflectiveInjector` is now deprecated as it will be remove. Use
`Injector.create` as a replacement.
closes#18496
FormControls, FormGroups, and FormArrays now optionally accept an options
object as their second argument. Validators and async validators can be
passed in as part of this options object (though they can still be passed
in as the second and third arg as before).
```ts
const c = new FormControl(, {
validators: [Validators.required],
asyncValidators: [myAsyncValidator]
});
```
This commit also adds support for passing arrays of validators and async
validators to FormGroups and FormArrays, which formerly only accepted
individual functions.
```ts
const g = new FormGroup({
one: new FormControl()
}, [myPasswordValidator, myOtherValidator]);
```
This change paves the way for adding more options to AbstractControls,
such as more fine-grained control of validation timing.
Angular can make many assumptions about its event handlers. As a result
the bookkeeping for native addEventListener is significantly cheaper
than Zone's addEventLister which can't make such assumptions.
This change bypasses the Zone's addEventListener if present and always
uses the native addEventHandler. As a result registering event listeners
is about 3 times faster.
PR Close#18107
HttpClient is an evolution of the existing Angular HTTP API, which exists
alongside of it in a separate package, @angular/common/http. This structure
ensures that existing codebases can slowly migrate to the new API.
The new API improves significantly on the ergonomics and features of the legacy
API. A partial list of new features includes:
* Typed, synchronous response body access, including support for JSON body types
* JSON is an assumed default and no longer needs to be explicitly parsed
* Interceptors allow middleware logic to be inserted into the pipeline
* Immutable request/response objects
* Progress events for both request upload and response download
* Post-request verification & flush based testing framework
Destructuring of the form:
function foo({a, b}: {a?, b?} = {})
breaks strictNullChecks, due to the TypeScript bug https://github.com/microsoft/typescript/issues/10078.
This change eliminates usage of destructuring in function argument lists in cases where it would leak
into the public API .d.ts.
With 4.2, we introduced the min and max validator directives. This was actually a breaking change because their selectors could include custom value accessors using the min/max properties for their own purposes.
For now, we are rolling back the change by removing the exports. At the least, we should wait to add them until a major version. In the meantime, we will have further discussion about what the best solution is going forward for all validator directives.
Closes#17491.
----
PR #17551 tried to roll this back, but did not remove the dead code. This failed internal tests that were checking that all declared directives were used.
This PR rolls back the original PR and commit the same as #17551 while also removing the dead code.
With 4.2, we introduced the min and max validator directives. This was actually a breaking change because
their selectors could include custom value accessors using the min/max properties for their own purposes.
For now, we are rolling back the change by removing the exports.
Closes#17491.
Previously the RequestOptions/ResponseOptions classes had constructors
with a destructured argument hash (represented by the
{Request,Response}OptionsArgs type). This type consists entirely of
optional members.
This produces a .d.ts file which includes the constructor declaration:
constructor({param, otherParam}?: OptionsArgs);
However, this declaration doesn't type-check properly. TypeScript
determines the actual type of the hash parameter to be OptionsArgs | undefined,
which it then concludes does not have a `param` or `otherParam` member.
This is a bug in TypeScript ( https://github.com/microsoft/typescript/issues/10078 ).
As a workaround, destructuring is moved inside the method, where it does not produce
broken artifacts in the .d.ts.
Fixes#16663.
`flush()` can now be used from within fakeAsync tests to simulate moving
time forward until all macrotask events have been cleared from the
event queue.
* refactor(core): provide error message in stack for reflective DI
Fixes#16355
* fix(compiler): make AOT work with `noUnusedParameters`
Fixes#15532
* refactor: use view engine also for `NgModuleFactory`s
This is a prerequisite for being able to mock providers
in AOTed code later on.
This commit fixes a regression where `ngModel` no longer syncs
letter by letter on Android devices, and instead syncs at the
end of every word. This broke when we introduced buffering of
IME events so IMEs like Pinyin keyboards or Katakana keyboards
wouldn't display composition strings. Unfortunately, iOS devices
and Android devices have opposite event behavior. Whereas iOS
devices fire composition events for IME keyboards only, Android
fires composition events for Latin-language keyboards. For
this reason, languages like English don't work as expected on
Android if we always buffer. So to support both platforms,
composition string buffering will only be turned on by default
for non-Android devices.
However, we have also added a `COMPOSITION_BUFFER_MODE` token
to make this configurable by the application. In some cases, apps
might might still want to receive intermediate values. For example,
some inputs begin searching based on Latin letters before a
character selection is made.
As a provider, this is fairly flexible. If you want to turn
composition buffering off, simply provide the token at the top
level:
```ts
providers: [
{provide: COMPOSITION_BUFFER_MODE, useValue: false}
]
```
Or, if you want to change the mode based on locale or platform,
you can use a factory:
```ts
import {shouldUseBuffering} from 'my/lib';
....
providers: [
{provide: COMPOSITION_BUFFER_MODE, useFactory: shouldUseBuffering}
]
```
Closes#15079.
PR Close#15256
This is needed to support the corner cases:
- usage of a `ComponentFactory` that was created on the fly via `Compiler`
- overwriting of the `NgModuleRef` that is associated to a
`ComponentFactory` by the `ComponentFactoryResolver` from
which it was read.
Fixes#15241
The Router use the type `Params` for all of:
- position parameters,
- matrix parameters,
- query parameters.
`Params` is defined as follow `type Params = {[key: string]: any}`
Because parameters can either have single or multiple values, the type should
actually be `type Params = {[key: string]: string | string[]}`.
The client code often assumes that parameters have single values, as in the
following exemple:
```
class MyComponent {
sessionId: Observable<string>;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.sessionId = this.route
.queryParams
.map(params => params['session_id'] || 'None');
}
}
```
The problem here is that `params['session_id']` could be `string` or `string[]`
but the error is not caught at build time because of the `any` type.
Fixing the type as describe above would break the build because `sessionId`
would becomes an `Observable<string | string[]>`.
However the client code knows if it expects a single or multiple values. By
using the new `ParamMap` interface the user code can decide when it needs a
single value (calling `ParamMap.get(): string`) or multiple values (calling
`ParamMap.getAll(): string[]`).
The above exemple should be rewritten as:
```
class MyComponent {
sessionId: Observable<string>;
constructor(private route: ActivatedRoute) {}
ngOnInit() {
this.sessionId = this.route
.queryParamMap
.map(paramMap => paramMap.get('session_id') || 'None');
}
}
```
Added APIs:
- `interface ParamMap`,
- `ActivatedRoute.paramMap: ParamMap`,
- `ActivatedRoute.queryParamMap: ParamMap`,
- `ActivatedRouteSnapshot.paramMap: ParamMap`,
- `ActivatedRouteSnapshot.queryParamMap: ParamMap`,
- `UrlSegment.parameterMap: ParamMap`
DEPRECATION:
- the arguments `inputs` / `outputs` / `ngContentSelectors` of `downgradeComponent`
are no longer used as Angular calculates these automatically now.
- Compiler.getNgContentSelectors is deprecated. Use
ComponentFactory.ngContentSelectors instead.
ErrorHandler can not throw errors because it will unsubscribe itself from
the error stream.
Zones captures errors and feed it into NgZone, which than has a Rx Observable
to feed it into ErrorHandler. If the ErroHandler throws, then Rx will teardown
the observable which in essence causes the ErrorHandler to be removed from the
error handling. This implies that the ErrorHandler can never throw errors.
Closes#14949Closes#15182Closes#14316
Observable subscriptions from previous validation runs should be canceled
before a new subscription is created for the next validation run.
Currently the subscription that sets the errors is canceled properly,
but the source observable created by the validator is not. While this
does not affect validation status or error setting, the source
observables will incorrectly continue through the pipeline until they
complete. This change ensures that the whole stream is canceled.
AsyncValidatorFn previously had an "any" return type, but now it more
explicitly requires a Promise or Observable return type. We don't
anticipate this causing problems given that any other return type
would have caused a runtime error already.
DEPRECATION:
- the arguments `inputs` / `outputs` / `ngContentSelectors` of `downgradeComponent`
are no longer used as Angular calculates these automatically now.
- Compiler.getNgContentSelectors is deprecated. Use
ComponentFactory.ngContentSelectors instead.
* feat(common): support `as` syntax in template/* bindings
Closes#15020
Showing the new and the equivalent old syntax.
- `*ngIf="exp as var1”`
=> `*ngIf="exp; let var1 = ngIf”`
- `*ngFor="var item of itemsStream |async as items”`
=> `*ngFor="var item of itemsStream |async; let items = ngForOf”`
* feat(common): convert ngIf to use `*ngIf="exp as local“` syntax
* feat(common): convert ngForOf to use `*ngFor=“let i of exp as local“` syntax
* feat(common): expose NgForOfContext and NgIfContext
fixes#12869fixes#12889fixes#13885fixes#13870
Before this change there was a single injector tree.
Now we have 2 injector trees, one for the modules and one for the components.
This fixes lazy loading modules.
See the design docs for details:
https://docs.google.com/document/d/1OEUIwc-s69l1o97K0wBd_-Lth5BBxir1KuCRWklTlI4
BREAKING CHANGES
`ComponentFactory.create()` takes an extra optional `NgModuleRef` parameter.
No change should be required in user code as the correct module will be used
when none is provided
DEPRECATIONS
The following methods were used internally and are no more required:
- `RouterOutlet.locationFactoryResolver`
- `RouterOutlet.locationInjector`
This API was introduced only in a beta release, and is being removed because we found it to be incorrect prior to launch. For more information about why this is being removed, see https://github.com/angular/angular/pull/15050.
BREAKING CHANGE:
Perviously, any provider that had an ngOnDestroy lifecycle hook would be created eagerly.
Now, only classes that are annotated with @Component, @Directive, @Pipe, @NgModule are eager. Providers only become eager if they are either directly or transitively injected into one of the above.
This also makes all `useValue` providers eager, which
should have no observable impact other than code size.
EXPECTED IMPACT:
Making providers eager was an incorrect behavior and never documented.
Also, providers that are used by a directive / pipe / ngModule stay eager.
So the impact should be rather small.
Fixes#14552
The main use case for the generated source maps is to give
errors a meaningful context in terms of the original source
that the user wrote.
Related changes that are included in this commit:
* renamed virtual folders used for jit:
* ng://<module type>/module.ngfactory.js
* ng://<module type>/<comp type>.ngfactory.js
* ng://<module type>/<comp type>.html (for inline templates)
* error logging:
* all errors that happen in templates are logged
from the place of the nearest element.
* instead of logging error messages and stacks separately,
we log the actual error. This is needed so that browsers apply
source maps to the stack correctly.
* error type and error is logged as one log entry.
Note that long-stack-trace zone has a bug that
disables source maps for stack traces,
see https://github.com/angular/zone.js/issues/661.
BREAKING CHANGE:
- DebugNode.source no more returns the source location of a node.
Closes 14013
This can be used to e.g. add the NoopAnimationsModule by default:
```
TestBed.initTestEnvironment([
BrowserDynamicTestingModule,
NoopAnimationsModule
], platformBrowserDynamicTesting());
```