This commit exposes the `standalone` flag on `@Directive`, `@Component`, and
`@Pipe`, effectively making standalone components a part of Angular's public
API. As part of this operation, it also implements JIT compilation for
standalone types.
Standalone types are Angular-decorated types which act as their own
"declarations", where they would otherwise be declared in an NgModule.
Marking an Angular type as standalone means that it can be used directly in
other standalone components and in NgModules, without needing an associated
NgModule to depend on it. In the case of a standalone component, template
dependencies which would otherwise be specified by an NgModule are instead
specified directly on the component itself, via the `imports` field. Other
standalone types can be imported, as well as NgModules.
PR Close#45687
This commit extracts the `importProvidersFrom` function and associated
machinery into a separate file, as opposed to being colocated with
`R3Injector`. Separating these functions will mitigate potential future
circular dependencies as `importProvidersFrom` starts being used in
different parts of the codebase.
PR Close#45687
add the ariaCurrentWhenActive input to the RouterLinkActive directive so that
users can easily set the aria-current property to their active router
links
resolves#35051
PR Close#45167
DEPRECATED:
The `resolver` argument of the `RouterOutletContract.activateWith` function and the `resolver` field of the `OutletContext` class are deprecated. Passing component factory resolvers are no longer needed. The `ComponentFactoryResolver`-related symbols were deprecated in `@angular/core` package since v13.
PR Close#45597
The current API for `activateWith` uses the deprecated
`ComponentFactoryResolver`. The replacement for this is to use
`EnvironmentInjector`. That is, instead of
```
const factory = componentFactoryResolver.resolveComponentFactory(component);
location.createComponent(factory, location.length, injector);
```
the replacement would be
```
location.createComponent(
component, {index: location.length, injector, environmentInjector});
```
PR Close#45597
Currently, the only way to specify new providers for a `Route` and the
children is to create a new `NgModule` with those providers and use the
`loadChildren` feature. This is pretty confusing and a wholly indirect
way of accomplishing this task. With this commit, developers will be
able to specify a list of providers directly on the `Route` itself.
These providers will apply the that route and its children.
This feature was inspired by the upcoming standalone components feature.
This ties in there because, as mentioned before, the prior art for lazy
loading configs was to load an `NgModule`. This loaded module contained
new route configs _and_ could specify new providers. Separating those
two concepts, there should be a way to load _just_ some new routes, but
there should also be a way to specify new providers as well (something
you could do in the `NgModule` world and now will be able to do in the
world without any `NgModule` through this feature).
PR Close#45673
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
This commit adds a type field to .d.ts metadata for directives, components,
and pipes which carries a boolean literal indicating whether the given type
is standalone or not. For backwards compatibility, this flag defaults to
`false`.
Tests are added to validate that standalone types coming from .d.ts files
can be correctly imported into new standalone components.
PR Close#45672
BREAKING CHANGE:
The type of `component` on `ActivatedRoute` and `ActivatedRouteSnapshot`
includes `string`. In reality, this is not the case. The component
cannot be anything other than a component class.
PR Close#45625
This wasn't exactly possible before because the `RouterConfigLoader` was
not an Injectable so there wasn't a straightforward way to share
information between `ApplyRedirects` and the preloader. They each had
their own implementation so they needed to store the values on the
`Route` so they both had access to them. I imagine this was the case
because trying to inject `Router` (to get access to the events) into the
preloader would have caused a circular dependency.
This refactor co-locates the loading details with the loader itself
rather than leaking implementation into the public route config and
mutating the object in an awkward way. This also promotes
`RouterConfigLoader` to a proper `Injectable` so data can be shared
throughout the system.
PR Close#45656
This commit implements the `destroy` method on the `ApplicationRef` class. This feature is a preparation for the new logic to bootstrap (and teardown) standalone components (without going through the `NgModuleRef` destroy), which would return an instance of the `ApplicationRef` (the current bootstrap APIs return an instance of the `NgModuleRef`).
PR Close#45624
This commit adds a new internal scope to `R3Injector` for
`EnvironmentInjector`s specifically. This will allow us to scope services to
the environment side of the injector hierarchy specifically, as opposed to
the `'any'` scope which also includes view-side injectors created via
`Injector.create`. For now, this functionality is not exposed publicly, but
is available to use within `@angular/core` only.
PR Close#45626
This commit exposes a new `EnvironmentInjector` abstraction, which
generalizes the "module injector" concept to injectors that are not based on
NgModules.
An EnvironmentInjector is a conceptual analogue of an `NgModuleRef` - it
represents an injector on the former "module" DI hierarchy in Angular (now
renamed to the "environment injector hierarchy"). Environment injectors are
created via the `createEnvironmentInjector` function from a list of
`Provider`s.
For backwards compatibility with current code using `NgModuleRef`,
`EnvironmentInjector`s are wrapped by an adapter `NgModuleRef`
implementation, so injecting `NgModuleRef` always returns the latest
`EnvironmentInjector`, even if that injector was not based on an NgModule.
Conversely, NgModule-based `NgModuleRef`s created via `createNgModuleRef`
are _also_ `EnvironmentInjector`s.
PR Close#45626
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
BREAKING CHANGE:
Since Ivy, TestBed doesn't use AOT summaries. The `aotSummaries` fields in TestBed APIs were present, but unused. The fields were deprecated in previous major version and in v14 those fields are removed. The `aotSummaries` fields were completely unused, so you can just drop them from the TestBed APIs usage.
PR Close#45487
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
The `LoadChildrenCallback` type previously included `any` in the
possible return value union for `Promise`. This is too loose and should
be restricted to values that are actually supported.
BREAKING CHANGE: When returning a `Promise` from the
`LoadChildrenCallback`, the possible type is now restricted to
`Type<any>|NgModuleFactory<any>` rather than `any`.
PR Close#45524
The API golden Bazel rule has changed in the shared dev-infra code. Instead
of putting golden API reports into the golden folder as per their original
location in the NPM package, golden reports are now stored based on the
package exports. This makes it more obvious how entry-points are consumable
As part of this change, since the API golden rule now consutls the NPM package
`exports` field, the `localize/tools` entry-point golden file is now generated.
Previously it wasn't generated due to it not having a secondary entry-point
`package.json` file. Such package json files should not be needed anymore
and will be gone in future APF versions.
PR Close#45461
The `relativeLinkResolution` option was added as an option to opt-in to
corrected behavior when generating links relative to a route that has an
empty path parent. This was needed to avoid a breaking change. Since
then, we have switched the default to be the corrected behavior.
It's time to close the turn the lights off on this option so we no
longer have to maintain and document buggy behavior.
PR Close#45308
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
In early versions of Angular, it was sometimes necessary to provide a
`moduleId` to `@Component` metadata, and the common pattern for doing this
was to set `moduleId: module.id`. This relied on the bundler to fill in a
value for `module.id`.
However, due to the superficial similarity between `Component.moduleId` and
`NgModule.id`, many users ended up setting `id: module.id` in their
NgModules. This is an anti-pattern that has a few negative effects,
including preventing the NgModule from tree-shaking properly.
This commit changes the compiler to ignore `id: module.id` in NgModules, and
instead provide a warning which suggests removing the line entirely.
PR Close#45024
warn developers when they are trying to animate non-animatable CSS
properties so that can more easily understand why something is not being
animated as they would expect it to
resolves#27577
PR Close#45212
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
When the service worker checks for an update and finds that the version on the server is the same as
the version locally installed, it currently noops. This change introduces an event which it emits
in this situation which notifies clients a check has occurred without error and no update was found.
PR Close#45216
Adds support for passing in an optional injector when creating an embedded view through `ViewContainerRef.createEmbeddedView` and `TemplateRef.createEmbeddedView`. The injector allows for the DI behavior to be customized within the specific template.
This is a second stab at the changes in #44666. The difference this time is that the new injector acts as a node injector, rather than a module injector.
Fixes#14935.
PR Close#45156
This commit updates the `NgLocalization` token to become tree-shakable (vs using a direct reference to that token in the `providers` section of the `CommonModule`). The `NgLocalization` token is used for apps that use i18n and for other apps it would be excluded from the bundle.
PR Close#45118
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
Adds support for passing in an optional injector when creating an embedded view through `ViewContainerRef.createEmbeddedView` and `TemplateRef.createEmbeddedView`. The injector allows for the DI behavior to be customized within the specific template.
This is a second stab at the changes in #44666. The difference this time is that the new injector acts as a node injector, rather than a module injector.
Fixes#14935.
PR Close#45156
Route.pathMatch only allows `'full'|'prefix'` in reality. This commit
adjusts the type to be more strict and also adds a migration to adjust
existing code.
resolves#37469
BREAKING CHANGE:
The type of `Route.pathMatch` is now more strict. Places that use
`pathMatch` will likely need to be updated to have an explicit
`Route`/`Routes` type so that TypeScript does not infer the type as
`string`.
PR Close#45176
This change is a follow up to #45057 to make `AnimationDriver.getParentElement`
a required method, which allows removing the slow path for the animation
namespace insertion logic.
BREAKING CHANGE:
The `AnimationDriver.getParentElement` method has become required, so any
implementors of this interface are now required to provide an implementation
for this method. This breakage is unlikely to affect application developers,
as `AnimationDriver` is not expected to be implemented in user code.
PR Close#45114
The prior approach would consider all existing namespaces from back to front
to find the one that's the closest ancestor for a given host element. An
expensive `contains` operation was used which needed to traverse all the
way up the document root _for each existing namespace_. This commit implements
an optimization where the closest namespace is found by traversing up from
the host element, avoiding repeated DOM traversal.
Closes#45055
PR Close#45057
Moves the `ANIMATION_MODULE_TYPE` DI token into core so that libraries like Material don't have to introduce a dependency to animations only to figure out whether animations are disabled.
PR Close#44970
The `Location` creates the `_urlChangeSubscription` when the `onUrlChange` is called for the first time.
The subscription `next` function captures `this` and prevents the `Location` from being garbage collected
when the root view is removed.
PR Close#44901
This commit updates the `PatternValidator` class to inherit `AbstractValidatorDirective` to make it conistent with other validators.
Closes angular#42267
PR Close#44887
This commit updates `DebugNode` and `DebugElement` implementaitons to cleanup ViewEngine removal artifacts. There is no need for a separate interface and implementation class, so we can combine them now. This comment also gets rid of `R3` suffixes (denoting Ivy) in helper methods.
PR Close#44270
Make `StateKey` typesafe by narrowing the type.
BREAKING CHANGE: This may break invalid calls to `TransferState` methods.
This tightens parameter types of `TransferState` usage, and is a minor breaking change which may reveal existing problematic calls.
PR Close#23020
BREAKING CHANGE:
* The type of `initialUrl` is set to `string|UrlTree` but in reality,
the `Router` only sets it to a value that will always be `UrlTree`
* `initialUrl` is documented as "The target URL passed into the
`Router#navigateByUrl()` call before navigation" but the value
actually gets set to something completely different. It's set to the
current internal `UrlTree` of the Router at the time navigation
occurs.
With this change, there is no exact replacement for the old value of
`initialUrl` because it was enver intended to be exposed.
`Router.url` is likely the best replacement for this.
In more specific use-cases, tracking the `finalUrl` between successful
navigations can also be used as a replacement.
PR Close#43863
This commit implements the first phase of standalone components in the Angular
compiler. This mainly includes the scoping rules for standalone components
(`@Component({imports})`).
Significant functionality from the design is _not_ implemented by this PR,
including:
* imports of standalone components into NgModules.
* the provider aspect of standalone components
Future commits will address these issues, as we proceed with the design of
this feature.
PR Close#44812
This commit updates the logic of the `NgComponentOutlet` class to allow passing an `NgModule` as an input instead of passing an `NgModule` factory.
DEPRECATED:
The `ngModuleFactory` input of the `NgComponentOutlet` directive is deprecated in favor of a newly added `ngModule` input. The `ngModule` input accepts references to the NgModule class directly, without the need to resolve module factory first.
PR Close#44815
This commit refactors the `RuntimeError` class to support a short version of providing error messages:
```
throw new RuntimeError(
RuntimeErrorCode.INJECTOR_ALREADY_DESTROYED,
ngDevMode && 'Injector has already been destroyed.');
```
In prod mode, the second argument becomes `false` andn this commit extends the typings to support that.
This commit also contains a couple places were the `RuntimeError` class is used to demostrate the compact form.
PR Close#44783
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
We were using a number of generic objects as if they were maps and relying on delete to remove
properties. In order to improve performance, these have been switched to native maps.
PR Close#44482