Recent refactoring in the Router made services available via
`providedIn: 'root'`. However, some of these changes were not merged to
the patch branch. This commit updates the remaining services needed to
create the `Router` without `RouterModule` and adds a test to ensure it
works.
PR Close#47052
This commit updates the code to include the TransferState providers (used for serialization) into the `ServerModule` instead of having the need to import the `ServerTransferStateModule` separately.
The list of providers in the `ServerTransferStateModule` is now empty and importing it is a noop. This is not a breaking change, since the `ServerModule` must be included anyways to make server rendering work correctly.
PR Close#46899
This commit updates the `TransferState` to make it `providedIn: 'root'`. This makes the entire `BrowserTransferStateModule` module unnecessary, so it got deprecated as well.
The `ServerTransferStateModule` is still retained, but the `renderApplication` function now also includes the necessary tokens to serialize the `TransferState` automatically, so when using the `renderApplication` function, there is no need to include `ServerTransferStateModule` as well.
This change is a part of the ongoing efforts to update the shape of the FW APIs to make them standalone-friendly (so there is no need to import any NgModules).
PR Close#46879
The implementation of the `DefaultTitleStrategy` was modeled after the
existing strategy patterns in the Router. These patterns were developed
before the `providedIn` syntax for injectables. We can simplify the
model a lot by providing the default in the factory of the abstract
class.
Note that the other strategy patterns aren't touched in this PR due to
how long they've existed. Because they have been there for such a long
time, it's possible there will need to be some adjustments to code
if/when they are refactored to do the same.
PR Close#46876
This commit refactors the code to move some functions around to avoid circular dependencies in TS imports. The newly added functions are now located in the `packages/core/src/render3/component.ts` file (instead of `packages/core/src/render3/component_ref.ts`), which is a better place for them anyway.
This commit introduces a new function that allows creating a `ComponentRef` instance based on provided Component and a set of options. The function can be used to cover a number of use-cases where the `ComponentFactory` symbol was used previously.
Currently if the `ENVIRONMENT_INITIALIZER` token is not configured with `multi: true` flag, the code fails while trying to iterate over the value. This commit checks whether the `ENVIRONMENT_INITIALIZER` token value type is an array and throws a helpful error message.
PR Close#46829
This commit adds the following functions to the public API:
- provideAnimations
- provideNoopAnimations
The goal of those functions is to return a set of providers required to setup animations in an application. The functions are useful when the `bootstrapApplication` function is used to bootstrap an app. The functions allow to avoid the need to import `BrowserAnimationsModule` and `BrowserNoopAnimationsModule` NgModules.
PR Close#46793
This commit adds an extended diagnostics check that is similar to the nullish
coalescing check, but targeting optional chains. If the receiver expression
of the optional chain is non-nullable, then the extended diagnostic can report
an error or warning that can be fixed by changing the optional chain into a
regular access.
Closes#44870
PR Close#46686
This commit adds the `createNgModuleRef` function alias to the public API. The alias is called `createNgModule`. The `createNgModule` name is more consistent with the rest of the API surface, where functions that return `*Ref`s don't include the `Ref` into the function name, for example: `createPlatform`, `ViewContainerRef.createComponent`, etc.
DEPRECATED:
The `createNgModuleRef` is deprecated in favor of newly added `createNgModule` one.
PR Close#46789
This commit adds an extended diagnostic which warns when style suffixes such as '.px'
are used with attribute bindings (attr.width.px).
Fixes#36256
PR Close#46651
This commit adds the target `RouterStateSnapshot` to the
`NavigationError` so error handlers/subscribers can more easily
determine which navigation failed, including the matched `Route` configs
for the navigation. This information was previously not available
(neither in `NavigationError` nor the `Router#getCurrentNavigation()`).
fixes#27626
PR Close#46731
There are legitimate cases where access to an EnvironmentInjector
of a bootstrapped application is required / convenient. It will be also
required for support of standalone components with Angular elements.
PR Close#46665
In the case that a user accidentally forgot the let keyword, they dont get a very clear indicator of there being a problem.
They get an issue in the template iteration at runtime. This diagnostic will warn the user when the let keyword is missing.
PR Close#46683
`BootstrapOptions` is exposed through `PlatformRef#bootstrapModule` but
is not included in the public API so you cannot find it on angular.io.
This commit simply marks the interface as public API (as it should be).
PR Close#46679
This commit adds a stable cancelation code to the `NavigationCancel`
event. This code is acceptable for use in production whereas parsing the
`reason` string is not. This allows developers to determine more
specifically _why_ a navigation was canceled and perform different
actions in different scenarios.
PR Close#46675
This change adds the setInput method to the ComponentRef.
Previously users had to call `componentRef.instance['inputName']`
to change inputs of a dynamically created component. This had
several problems:
* OnPush components were not marked for check and thus very
difficult to test;
* input aliasing was not take into account - a property name
on a component could have been different from the actual input
name so setting input properties was fragile;
* manually setting input propertie would NOT trigger the
`NgOnChanges` lifecycle hook.
This modifications unifies `@Input` accross dynamically created
components and the ones referenced in templates. This also opens
doors to other changes: as an example router could use this new
method to set `@Input`s from router params.
Closes#12313Closes#22567
PR Close#46641
This custom error message for invalid guards requires a fair bit of
extra logic in several places. This change reduces special logic for an error
case that would fail anyways. Additionally, there were already a couple
places that _did not_ have this special error and we have not seen any
indication that there is more confusion for those (resolvers and canMatch).
PR Close#46678
`inject()` originated as a private API and was made public to support
`InjectionToken` factories in Ivy. For code-size and performance reasons,
when we code generate `inject()` calls we use a bit field to indicate the
various injection modes (optional, skip-self, etc). However, this doesn't
make for a very nice public API.
This commit introduces an alternative object-based API for options. All 4
flags are supported as `boolean` fields on an options object, and converted
to bit flags internally. If TypeScript can prove that `optional` injection
is not requested, it can narrow the return type and remove the `null` type.
DEPRECATED:
The bit field signature of `inject()` has been deprecated, in favor of the
new options object. Correspondingly, `InjectFlags` is deprecated as well.
Fixes#46251
PR Close#46649
This commit introduces a new API on `EnvironmentInjector` to run a function
in the context of the injector. This makes `inject()` available within the
body of the function to inject dependencies. We expect this functionality to
be very useful for designing ergonomic APIs both in and out of Angular, as
it should allow for a smaller and more functional API style.
Note that it's possible to implement nearly identical functionality in user
code already today:
```typescript
function runInContext<T>(injector: EnvironmentInjector, fn: () => T): T {
const token = new InjectionToken<T>('TOKEN');
const tmpInjector = createEnvironmentInjector([
{provide: token, useFactory: () => fn()},
], injector);
return tmpInjector.get(token);
}
```
The factory provider for `token` in this example runs in the context of the
`tmpInjector`, giving it access to `inject` that can retrieve values from
`injector` as well. This is nearly identical, although because of the child
injector `self` and `skipSelf` injection options don't function correctly.
PR Close#46653
https://angular.io/guide/attribute-binding#attribute-class-and-style-bindings
Angular supports `attr.`, `style.`, and `class.` binding prefixes to
bind attributes, styles, and classes. If the key does not have the
binding syntax `[]` or the value does not have an interpolation `{{}}`,
the attribute will not be interpreted as a binding.
This diagnostic warns the user when the attributes listed above will not
be interpreted as bindings.
resolves#46137
PR Close#46161
Previously, when instantiating a component, Angular would look in the DI
hierarchy for `RendererFactory2`. Any DI tree which rolls up through an
application injector (that is, one created with `BrowserModule`) should be
able to provide this interface. If not found, Angular would switch to the
experimental `Renderer3` mechanism. This switch was designed this way,
because it allowed for the creation of experimental applications where
`RendererFactory2` was not included in the bundle at all.
In this commit, instead of automatically falling back on `Renderer3`-style
rendering, an error is raised instead if `RendererFactory2` is missing from
the DI hierarchy.
PR Close#46605
This commit updates the directives presents in the `CommonModule` and annotates them with the `standalone: true` flag. With that flag, the directives can now be imported individually, as well as imported via the `CommonModule`.
PR Close#46469
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
This commit updates the pipes presents in the `CommonModule` and annotates them with the `standalone: true` flag. With that flag, the pipes can now be imported individually, as well as imported via the `CommonModule`.
PR Close#46401
This change separates the router initializer into different providers.
While it does not actually change the tree-shakeablity or the public
API, it does move us towards a world that _could_ do this. That is,
instead of `initialNavigation: 'disabled'`, users could use
`provideDisabledInitialNavigation` in the `bootstrapApplication` call
and none of the code for `initialNavigation: 'enabledBlocking'` would be
included in the application.
PR Close#46215
Extracting preloading to a provider moves us towards
thinking about a world where `ExtraOptions` doesn't exist to control
behaviors that are opt-in/opt-out. Instead, these behaviors could be
controlled by the presence (or lackthereof) of the providers which has
the functionality. This is relevant to a world in which we no longer
have the `RouterModule` but instead have something like `provideRouter`
where the features are tree-shakeable.
This change _does not_ make the `RouterPreloader` tree-shakeable inside
`RouterModule.forRoot` because the compiler cannot statically determine
whether it's needed. However, in the `provideRouter` world without
`forRoot`, preloading could be exposed through the provider function
instead, making the `RouterPreloader` and `PreloadingStrategy`
implementations tree-shakeable for those that don't use it (which is the
default - no preloading).
PR Close#46215
Extracting the `'enableTracing'` option to a provider moves us towards
thinking about a world where `ExtraOptions` doesn't exist to control
behaviors that are opt-in/opt-out. Instead, these behaviors could be
controlled by the presence (or lackthereof) of the providers which has
the functionality. This is relevant to a world in which we no longer
have the `RouterModule` but instead have something like `provideRouter`
where the features are tree-shakeable.
This change does not affect the current `RouterModule.forRoot` behavior,
tree-shakeability of the option, or existence of `enableTracing` on the
`ExtraOptions`.
PR Close#46215
Currently it's not possible to return plain `UrlTree` from `CanMatchFn`,
only wrapped `UrlTree` into Observable or Promise is allowed.
These changes allow to return `UrlTree` from `CanMatchFn`.
PR Close#46455
The `CanMatchFn` is already exposed in the type signature for `canMatch` on the
`Route`. This function type should already be exposed as public API but was
missed in the initial implementation because the older guards use the `any` type
instead.
PR Close#46394
Previously, the `createEnvironmentInjector` function allowed creating an instance of an EnvironmentInjector without providing a parent injector. This resulted in an injector instance, which was detached from the DI tree, thus having limited value. This commit updates the types of the `createEnvironmentInjector` function to make the parent injector a required argument.
PR Close#46397
Currently we have two main types of guards:
`CanLoad`: decides if we can load a module (used with lazy loading)
`CanActivate` and friends. It decides if we can activate/deactivate a route.
So we always decide where we want to navigate first ("recognize") and create a new router state snapshot. And only then we run guards to check if the navigation should be allowed.
This doesn't handle one very important use case where we want to decide where to navigate based on some data (e.g., who the user is).
I suggest to add a new guard that allows us to do that.
```
[
{path: 'home', component: AdminHomePage, canUse: [IsAdmin]},
{path: 'home', component: SimpleHomePage}
]
```
Here, navigating to '/home' will render `AdminHomePage` if the user is an admin and will render 'SimpleHomePage' otherwise. Note that the url will remain '/home'.
With the introduction of standalone components and new features in the Router such as `loadComponent`,
there's a case for deprecating `CanLoad` and replacing it with the `CanMatch` guard. There are a few reasons for this:
* One of the intentions of having separate providers on a Route is that lazy
loading should not be an architectural feature of an application. It's an
optimization you do for code size. That is, there should not be an architectural
feature in the router to specifically control whether to lazy load something or
not based on conditions such as authentication. This is a slight nuanced
difference between the proposed canUse guard: this guard would control whether
you can use the route at all and as a side-effect, whether we download the code.
`CanLoad` only specified whether the code should be downloaded so canUse is more powerful and more appropriate.
* The naming of `CanLoad` will be potentially misunderstood for the `loadComponent` feature.
Because it applies to `loadChildren`, it feels reasonable to think that it will
also apply to `loadComponent`. This isn’t the case: since we don't need
to load the component until right before activation, we defer the
loading until all guards/resolvers have run.
When considering the removal of `CanLoad` and replacing it with `CanMatch`, this
does inform another decision that needed to be made: whether it makes sense for
`CanMatch` guards to return a UrlTree or if they should be restricted to just boolean.
The original thought was that no, these new guards should not allow returning UrlTree
because that significantly expands the intent of the feature from simply
“can I use the route” to “can I use this route, and if not, should I redirect?”
I now believe it should allowed to return `UrlTree` for several reasons:
* For feature parity with `CanLoad`
* Because whether we allow it as a return value or not, developers will still be
able to trigger a redirect from the guards using the `Router.navigate` function.
* Inevitably, there will be developers who disagree with the philosophical decision
to disallow `UrlTree` and we don’t necessarily have a compelling reason to refuse this as a feature.
Relates to #16211 - `CanMatch` instead of `CanActivate` would prevent
blank screen. Additional work is required to close this issue. This can
be accomplished by making the initial navigation result trackable (including
the redirects).
Resolves#14515
Replaces #16416Resolves#34231Resolves#17145Resolves#12088
PR Close#46021
This commit adds an extended diagnostics check that verifies that all control flow directives (such as `ngIf`, `ngFor`) have the necessary directives imported in standalone components. Currently there is no diagnostics produced for such cases, which makes it harder to detect and find problems.
PR Close#46146
`ngComponentOutlet` already handles null/undefined values, but the types don't reflect that. These changes update the types.
Fixes#45716.
PR Close#46280