`importProvidersFrom` provides a bridge from the world of NgModule-based DI
configuration to the new, "standalone" world of direct providers and
environment injectors. Early user feedback suggested some confusion around
where this function was supposed to be used, particularly around importing
NgModule-based providers into standalone component `providers` arrays, which
is not the intended use. This confusion is exacerbated by the fact that due
to the unified `Provider` type, this kind of misconfiguration was happily
accepted by the type system.
This commit changes the return type of `importProvidersFrom` to wrap the
returned providers in an opaque type that prevents them from being used in
component provider contexts. This, together with stronger documentation
around the purpose and functionality of `importProvidersFrom`, should
address some of the above confusion.
PR Close#45838
This commit updates the `renderApplication` function to move the `appId` argument to the options object. The goal is to achieve a symmetry with the `bootstrapApplication` call (use to bootstrap apps for the browser environment).
PR Close#45844
This commit updates the logic to detect a situation when a standalone component is used in the NgModule-based bootstrap (`@NgModule.bootstrap`). Both AOT and JIT compilers are updated to handle this situation.
PR Close#45825
Allows to provide a TestBed option to throw on unknown elements in templates:
```ts
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(), {
errorOnUnknownElements: true
}
);
```
The default value of `errorOnUnknownElements` is `false`, so this is not a breaking change.
PR Close#45479
Allows to provide a TestBed option to throw on unknown elements in templates:
```ts
getTestBed().initTestEnvironment(
BrowserDynamicTestingModule,
platformBrowserDynamicTesting(), {
errorOnUnknownElements: true
}
);
```
The default value of `errorOnUnknownElements` is `false`, so this is not a breaking change.
PR Close#45479
This commit adds the `renderApplication` function to bootstrap an Angular app using a root standalone component to support SSR scenarios.
PR Close#45785
Adds support for TypeScript 4.7. Changes include:
* Bumping the TS version as well as some Bazel dependencies to include https://github.com/bazelbuild/rules_nodejs/pull/3420.
* Adding a backwards-compatibility layer for calls to `updateTypeParameterDeclaration`.
* Making `LView` generic in order to make it easier to type the context based on the usage. Currently the context can be 4 different types which coupled with stricter type checking would required a lot of extra casting all over `core`.
* Fixing a bunch of miscellaneous type errors.
* Removing assertions of `ReferenceEntry.isDefinition` in a few of the language service tests. The field isn't returned by TS anymore and we weren't using it for anything.
* Resolving in error in the language service that was caused by TS attempting to parse HTML files when we try to open them. Previous TS was silently setting them as `ScriptKind.Unknown` and ignoring the errors, but now it throws. I've worked around it by setting them as `ScriptKind.JSX`.
PR Close#45749
There were two problems with the `importProvidersFrom` function related to
`ModuleWithProviders` values:
* The public type did not accept `ModuleWithProviders` values directly.
* The implementation of `walkProviderTree` delegates collection of MWP providers
to its caller, in order for the ordering of such providers to be correct.
However, `importProvidersFrom` was not performing that collection, causing MWP
providers passed in at the top level to be dropped.
PR Close#45722
Adds getState to LocationStrategy interface as it suppose to be the place to control all window.location interactions.
BREAKING CHANGE:
Adds new required class member that any implementors of the LocationStrategy will need to satisfy.
Location does not depend on PlatformLocation anymore.
PR Close#45648
Similarly to the symmetry being strengthened between children and loadChildren,
a new loadComponent property will be introduced as the asynchronous version of component.
This will allow for direct single-component lazy loading:
```
{path: 'lazy/a', loadComponent:
() => import('./lazy/a.component').then(m => m.ACmp)},
{path: 'lazy/b', loadComponent:
() => import('./lazy/b.component').then(m => m.BCmp)},
```
This option requires that the component being loaded is standalone and
is implemented as a runtime check.
Other notes:
* Components are not loaded until all guards and resolvers complete.
* Loading the component is included in the function passed to the router
preloading strategy
* `RouteConfigLoadStart` and `RouteConfigLoadEnd` events emit at the
start and end of the component loading
* `CanLoad` guards _do not_ apply to `loadComponent`. `canActivate`
should be used instead, just like you would do if it were simply
`component` instead.
PR Close#45705
This commit expands the `LoadChildrenCallback` to accept returning `Routes`
in addition to the existing `NgModule` type. In addition, it adds a
check to ensure these loaded routes all use standalone components.
The components must be standalone because if they were not,
we would not have the required `NgModule` which the component is declared in.
Existing API:
```
{path: 'lazy/route', loadChildren: import('./lazy').then(m => m.LazyModule)}
@NgModule({
imports: [
ExtraCmpModule,
RouterModule.forChild([
{path: 'extra/route', component: ExtraCmp},
]),
],
})
export class LazyModule {}
```
The new API for lazy loading route configs with standalone components
(no NgModule) is to expand `loadChildren` to allow returning simply a `Routes` array.
```
// parent.ts
{
path: 'parent',
loadChildren: () => import('./children').then(m => m.ROUTES),
}
// children.ts
export const ROUTES: Route[] = [
{path: 'child', component: ChildCmp},
];
```
Note that this includes minimal documentation updates. We need to
include a holistic update to the documentation for standalone components
in the future that includes this feature.
PR Close#45700
This commit adds 2 integration apps to verify the `bootstrapApplication` API behavior as well as keep track of the bundle size and retained symbols (tree-shaking).
PR Close#45674
This commit implements the `bootstrapApplication` function that allows bootstrapping an application and pass a standalone component as a root component.
PR Close#45674
The main bundle fell below the 500b threshold. Likely because the
global constant was fixed and is now tree-shakeable.
The actual diff in the commit is a little confusing since it makes it
seem that polyfills increased as part of this commit. This is not the
case but just a side-effect of us accumulating various changes which
are not reflected on a per-commit basis in the size golden.
The actual sizes in master were:
```
SUCCESS: Commit undefined uncompressed runtime did NOT cross size threshold of 500 bytes or >1% (expected: 1105, actual: 1102).
SUCCESS: Commit undefined uncompressed polyfills did NOT cross size threshold of 500 bytes or >1% (expected: 33846, actual: 33957).
SUCCESS: Commit undefined uncompressed main did NOT cross size threshold of 500 bytes or >1% (expected: 132392, actual: 131893).
```
Now with this change:
```
SUCCESS: Commit undefined uncompressed runtime did NOT cross size threshold of 500 bytes or >1% (expected: 1105, actual: 1102).
SUCCESS: Commit undefined uncompressed polyfills did NOT cross size threshold of 500 bytes or >1% (expected: 33846, actual: 33957).
FAIL: Commit undefined uncompressed main fell below expected size by 500 bytes or >1% (expected: 132392, actual: 131883).
```
PR Close#45405
This commit addresses two issues:
* The init entry-point currenly access code from another entry-point
using relative imports, resulting in code to be duplicated.
* The init types are now bundled as part of the ng_package APF rule.
There is an API extractor bundling issue with global module
augmentations.
API extractor does not properly handle module augmentation. We need to disable
dts bundling for this entry-point to ensure `$localize` remains globally accessible
for users. This is an option in the `ng_package` rule.
Note that this worked before because `localize/init` was a `ts_library` that did not
have its types bundled.
As part of this change, the `MessageId` and `TargetMessage` exports are
also made public. The localize exported functions rely on these types but
they were not exported.
Related to types, an exception is added for three private exports from the primary
entry-point so that they will show up in the API golden. These private
exports are re-exposed publicly in the init entry-point but no golden
would capture them due to the private symbol prefix. One might wonder
why the symbols are not guarded in the init golden. The reason is that
goldens never inline signatures from cross-entry-points/packages to avoid
duplication.
Lastly, the i18n integration test golden had to be updated because the
polyfills bundle increased slightly. After thorough and time-consuming
investigation, this mostly happens due to different mangle identifies
being used (the input code changed --> so the mangling determinism)
Size before this change:
```
SUCCESS: Commit undefined uncompressed runtime did NOT cross size threshold of 500 bytes or >1% (expected: 929, actual: 926).
SUCCESS: Commit undefined uncompressed main did NOT cross size threshold of 500 bytes or >1% (expected: 124544, actual: 124660).
SUCCESS: Commit undefined uncompressed polyfills did NOT cross size threshold of 500 bytes or >1% (expected: 34530, actual: 34641).
```
After:
```
SUCCESS: Commit undefined uncompressed runtime did NOT cross size threshold of 500 bytes or >1% (expected: 929, actual: 926).
SUCCESS: Commit undefined uncompressed main did NOT cross size threshold of 500 bytes or >1% (expected: 124544, actual: 124650).
FAIL: Commit undefined uncompressed polyfills exceeded expected size by 500 bytes or >1% (expected: 34530, actual: 35252).
```
Inspecting/comparing without mangling shows that the new changes would
actually result in a bundle reduction (potentially visible with
gzip/brotli):
```
➜ Desktop stat -f%z master-nomangle.js
101357
➜ Desktop stat -f%z with-changes-nomangle.js
101226
```
PR Close#45405
This commit implements the `StandaloneFeature` which provides for the
creation of standalone injectors, for those components which need them. The
feature-based implementation ensures the machinery for standalone injectors
is properly tree-shakable.
PR Close#45687
This commit refactors `importProvidersFrom` to support pulling providers
from the dependencies of a standalone component, in addition to NgModules.
Tests will be added in a future commit when standalone components can be
created without calling private APIs.
PR Close#45687
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
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
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
Previously, the `guide/compoent-style` page was used in e2e tests to
verify the behavior of `{@example}` dgeni tags. However, this guide has
been updated and no longer contains an `{@example}` tag.
This commit switches to using a different page (`api/common/NgIf`) that
does currently contain an `{@example}` tag.
(NOTE: This will also fix the [CI failures][1] in #45501.)
[1]: https://circleci.com/gh/angular/angular/1145424
PR Close#45551
currently if a user tries to navigate via keyboard, once the are
presented with search results, the search results panel remains
present and can potentially hide most of the content on the page,
in such case keyboard navigation will be severly hindered and
the only option for the user would be to go back to the seach input
text and clear its value, fix such inconvenience by looping the
focus in the header area close to the search results and the
results panel itself
note: an alternative implementation using the cdkTrapFocus has been
attempted in PR #45194, such alternative implementation presented a
number of (minor) drawbacks (including the increase main bundle size
due to the inclusion of the A11yModule), so it was agreed to proceed
with the manual implementation present in these changes instead.
PR Close#44989
This commit implements the next step of Angular's "standalone" functionality,
by allowing directives/components/pipes declared as `standalone` to be imported
into NgModules. Errors are raised when such a type is not standalone but is
included in an NgModule's imports.
PR Close#44973
Updates the AIO payload size goldens to reflect the Angular update
affecting both the `aio` and `aio_local` build (due to CLI devkit
changes affecting both goldens, and the Angular update also affecting
the non-local `aio` build / job).
Overall, the Material themes got a little larger, but this is
not caused by the framwork, so not relevant here.
PR Close#45461