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
Servers always decode + as a space, which is undesirable when one
actually wants to query for a plus.
BREAKING CHANGE:
Queries including + will now actually query for + instead of space.
Most workarounds involving custom codecs will be unaffected.
Possible server-side workarounds will need to be undone.
Fixes angular#11058
PR Close#45111
This commit bundles tests for standalone components that are possible after
previous implementation commits. Most new tests are compliance tests, but
a test is also included to validate that the template type-checking system
can work with standalone components as well.
PR Close#45672
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
This commit propagates the `isStandalone` flag for a component, directive,
or pipe during partial compilation of a standalone declaration. This flag
allows the linker to properly process a standalone declaration that it
encounters.
PR Close#45672
Standalone component scopes were first implemented in the
`ComponentDecoratorHandler` itself, due to an assumption that "standalone"
allowed for a localized analysis of the component's dependencies. However,
this is not strictly true. Other compiler machinery also needs to understand
component scopes, including standalone component scopes. A good example is
the template type-checking engine, which uses a `ComponentScopeReader` to
build full metadata objects (that is, metadata that considers the entire
inheritance chain) for type-checking purposes. Therefore, the
`ComponentScopeReader` should be able to give the scope for a standalone
component.
To achieve this, a new `StandaloneComponentScopeReader` is implemented, and
the return type of `ComponentScopeReader.getScopeForComponent` is expanded
to express standalone scopes. This cleanly integrates the "standalone"
concept into the existing machinery.
PR Close#45672
This commit adds an emit for standalone components of the
`StandaloneFeature`, which will support creation of standalone injectors and
any other mechanisms necessary for standalone component functionality at
runtime.
Using a feature allows for standalone functionality to be tree-shaken in
applications that aren't using them.
PR Close#45672
This commit expands on the unified dependency tracking in the previous
commit and adds tracking of NgModule dependencies. These are not used for
standard components, but are emitted for standalone components to allow the
runtime to roll up providers from those NgModules into standalone injectors.
PR Close#45672
Previously, the compiler tracked directives and pipes in template scopes
separately. This commit refactors the scope system to unify them into a
single data structure, disambiguated by a `kind` field.
PR Close#45672
Previously, the compiler would represent template dependencies of a
component in its component definition through separate fields (`directives`,
`pipes`).
This commit refactors the compiler/runtime interface to use a single field
(`dependencies`). The runtime component definition object still has separate
`directiveDefs` and `pipeDefs`, which are calculated from the `dependencies`
when the definition is evaluated.
This change is also reflected in partially compiled declarations. To ensure
compatibility with partially compiled code already on NPM, the linker
will still honor the old form of declaration (with separate fields).
PR Close#45672
`PipeSymbol` contains logic to detect changes in the public API surface of
pipes, which includes the pipe name. However, the pipe handler inadvertently
uses the pipe class name instead of the actual pipe name to initialize the
`PipeSymbol`, which breaks incremental compilation when pipe names change.
There is a test which attempts to verify that this logic is working, but the
test actually passes for a different reason. The test swaps the names of 2
pipes that are both used in a component, and asserts that the component is
re-emitted, theoretically because the public APIs of the pipes is changed.
However, the emit order of the references to the pipes depends on the order
in which they match in the template, which changes when the names are
swapped. This ordering dependency is picked up by the semantic dependency
tracking system, and is what actually causes the component to be re-emitted
and therefore the pipe test to pass in spite of the bug with name tracking.
This commit fixes the `PipeSymbol` initialization to use the correct pipe
name. The test is still flawed in that it's sensitive to the ordering of
pipe emits, but this ordering is due to change soon as a result of the
standalone components work, so this issue will be resolved in a future
commit.
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 commit updates one of the styling tests to reset perf counters, making it order-independent and non-flaky (previously the test got random failures depending on whether there are other tests invoked before).
PR Close#45670
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
The `EnvironmentInjector` should be used instead of `Injector` for the
lazy loading. A future refactor will further update `RouterOutlet` to
use this injector to create the component rather the deprecated
`ComponentFactoryResolver`.
PR Close#45671
In the standalone world, these concepts will no longer be one and the
same. You can load routes without them being inside an `NgModule` with
`RouterModule.forChild`. In addition, routes will be able to define
their own providers, which will be included in an injector that is not
necessarily lazy loaded.
PR Close#45593
The `Injector` is really the piece of information that the `Router` is
interested in keeping track of. Storing the `NgModuleRef` is somewhat
confusing based on how it's used later on. `RouterOutlet` uses it for the
`componentFactoryResolver`, but this is not needed anymore (and deprecated). In
fact, we can get back to the `NgModuleRef` anyways using the injector.
For now, that's what this change does. A different refactor will remove
the use of the `componentFactoryResolver` altogether.
Additionally, in the standalone world, we plan to implement a feature to
allow defining `providers` directly on the `Route`. This means there
won't be an associated `NgModuleRef` so this refactor prepares for that
feature.
PR Close#45593
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
This commit implements the `importProvidersFrom` function that allows
extracting a list of `Provider`s from a list of NgModule types. The
R3Injector which implements DI at the "module" level for Angular is
refactored to use this functionality under the hood.
This commit also implements `INJECTOR_INITIALIZER`, a DI multi-provider
token which is used to run initialization logic when an injector is created.
PR Close#45626
Previously there was a test ordering issue with the application_module_spec
tests where the value of `getLocaleId()` depended on the order in which
tests ran. Specifically, `setLocaleId()` lower-cases the current locale ID,
so the measured value in a test depended on whether a previous test had
called `setLocaleId()` (the difference between 'en-US' and 'en-us').
PR Close#45626
This links back each placeholder in a message to the original Angular template span which defines its expression. This is useful for understanding where each placeholder comes from in the context of the full message.
PR Close#45606
We throw an error when a directive is trying to extend a component, but we don't actually say which class is responsible which can be difficult to track down. These changes add the two class names to the error message.
PR Close#45658
We allow the path to contain both the `t.BoundAttribute` and `t.BoundEvent` for two-way
bindings but do not want the path to contain both the `t.BoundAttribute` with its
children when the position is in the value span because we would then logically create a path
that also contains the `PropertyWrite` from the `t.BoundEvent`. This early return condition
ensures we target just `t.BoundAttribute` for this case and exclude `t.BoundEvent` children.
Fixes https://github.com/angular/vscode-ng-language-service/issues/1626
PR Close#45582
This commit improves the error message that is thrown at runtime when multiple components match the same element. Now the error message contains names of classes that represent those components.
PR Close#45645
Lazy loaded configs are not validated at runtime like the initial set of
routes are. This change also validates lazy loaded configs right after
they're loaded.
BREAKING CHANGE: Lazy loaded configs are now also validated once loaded like the
initial set of routes are. Lazy loaded modules which have invalid Route
configs will now error. Note that this is only done in dev mode so
there is no production impact of this change.
Fixes#25431
PR Close#45526
Recently the navigation was on hold even at least one resolver didn't emit any value and completed, but another ones still are in progress to resolve any value. The changes cancel the navigation instantly if at least one resolver doesn't emit any value and completed.
PR Close#45621
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
We recently refactored how the ng package rule deals with static files.
As part of this refactoring, transitive files outside of the current
Bazel package were flagged as errors, while previously this was just
ignored. We need to revert back this behavior (even though code remains
much simpler and predicable now) since sass library targets for example
reference all transtive files in the default info and break packages then
PR Close#45622
There are two functions which do the same thing and are meant to search
for the closest loaded config in the `ActivatedRouteSnapshot` parent
tree. These can be combined to reduce code duplication.
One difference in the current implementation is the early exit for the
implementation in `activate_routes` when `route.component` is defined.
This early exit takes advantage of the fact that the component must then
also have a `RouterOutlet`, which injects `ComponentFactoryResolver`,
which would end up being the same one as what would be found if we
continued to look up the parent tree. This is only a tiny optimization
that will actually break when we add `providers` as a feature to the
`Route` config. In this scenario, we _must_ find the correct injector
in the parent routes and cannot rely on a parent `RouterOutlet` since
there may be some route with a providers list in between.
PR Close#45613
This commit updates an existing bootstrap logic to avoid referencing the `PlatformRef` instance to keep track of the platform status. Instead, we use platform injector, so that the `PlatformRef`can be tree-shaken away in the bootstrap logic for Standalone Components.
The motivation for this change is that retaining the `PlatformRef` class also retains NgModule-based bootstrap code, which would not be needed in case of Standalone Components.
PR Close#45519
This change adds code to compute the corrected value for a link,
regardless of the `relativeLinkResolution` value. Then, if the
`relativeLinkResolution` is set to `legacy` and differs from the correct
value, a warning is printed to the console in dev mode.
This change is meant to assist in notifying developers that they have
code which relies on the deprecated, broken behavior so they can fix and
update the code before the `relativeLinkResolution` option is fully
removed.
PR Close#45523
Our logic for generating code from an AST uses recursion which limits the number of expressions we can nest before we reach the call stack limit. These changes add a limit in order to avoid errors in some cases where the chains become extremely long.
Fixes#45564.
PR Close#45574
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 commit removes the `ComponentFactoryResolver` as a constructor argument of the `ApplicationRef` class. This makes it lazily instantiated + simplifies further refactoring in a context of Standalone Components.
PR Close#45507
This commit refactors the set of hardcoded platform core providers into tree-shakable providers.
In addition to making them tree-shakable, this would also avoid the need to rely on the platform creation logic in an upcoming bootstrap logic for Standalone Components.
PR Close#45506
Angular now uses Jasmine 2.8 as a minimum version (required by
protractor; most of it is using ^3.5.0 which currently resolves to
3.99.0), which makes this shim obsolete - all versions of Jasmine used
have Map comparison built in.
This shim causes problems for custom equality checkers - when using a
Map containing types needing a custom equality check, this fails
because the call to `jasmine.matchersUtil.equals` from the shim does not
use any of the custom equality matchers.
PR Close#45521