Speeds up the dev-turnaround by only bundling types when packaging. Currently
bundling occurs for all the `ng_module` targets in devmode.
This has various positive benefits:
* Avoidance of this rather slower operation in development
* Makes APF-built packages also handle types for `ts_library` targets consistently.
* Allows us to ensure APF entry-points have `d.ts` _always_ bundled (working with ESM
module resolution in TypeScript -- currently experimental)
* Allows us to remove the secondary `package.json` files from APF (maybe APF v14? - seems
low-impact). This would clean-up the APF even more and fix resolution issues (like in Vite)
PR Close#45405
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
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
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
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
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 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
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
Updates us to version 4.0 of Jasmine and fixes some errors that were the result of us depending upon deprecated APIs. We need to do this both to stay up to date and because it was going to break eventually, because one of the Bazel packages was logging a deprecation warning that version 4.0 was required.
There were also some cases where the state of `ngDevMode` had started leaking out between tests.
PR Close#45558
Updates us to version 4.0 of Jasmine and fixes some errors that were the result of us depending upon deprecated APIs. We need to do this both to stay up to date and because it was going to break eventually, because one of the Bazel packages was logging a deprecation warning that version 4.0 was required.
There were also some cases where the state of `ngDevMode` had started leaking out between tests.
PR Close#45558
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
in layers
Right now route static data are collected from its parents based on the logic
described in `inheritedParamsDataResolve()`, merged into a single object
and then merged again with merged data from resolvers. This means that a
child's data can be overriden by a resolver in its parent (#34361).
However, what is the expected behavior is not described in the documentation.
This PR changes this behavior and merges static data and resolved data
in "layers" (route by route) so child's static data and resolved data
cannot be overriden by their parents.
Fixes#34361
PR Close#45276
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
.substr() is deprecated so we replace it with functions which work similarily but aren't deprecated
Signed-off-by: Tobias Speicher <rootcommander@gmail.com>
PR Close#45397
* `tree` function now accepts the old root rather than the old
`UrlTree`. The `urlTree` argument was only used to get the `root`.
This change makes it more clear what that pararmeter is used for and
what's actually being used
* Move the `oldRoot` (previously `urlTree`) to be the first argument of `tree`.
This change now mirrors the argument order for `replaceSegment` and
can be read from left to right more easily "in this root,
replace this old segment group with this new segment group".
* Extract `newRoot` to a variable. This just makes it more clear what's
going on at the end rather than combining a bunch of operations into
one.
These changes are being made so that hopefully a future refactor can be
done which does not rely on the `urlTree` argument at all in the
`createUrlTree` function. These refactorings will make it easier to see
1:1 functionlity in these various places.
PR Close#45306
Node.js v12 will become EOL on 2022-04-30. As a result, Angular CLI v14 will no longer support Node.js v12.
BREAKING CHANGE:
Support for Node.js v12 has been removed as it will become EOL on 2022-04-30. Please use Node.js v14.15 or later.
PR Close#45286
This commit removes special (undocumented) logic in the Router code that is
meant to prevent duplicate navigations that result from location syncs in
AngularJS/Angular hybrid applications.
The duplicate navigations can occur when both the Router and the AngularJS sync
code detect a location change via a popstate/hashchange event. When this
happens, the Angular Router schedules a navigation to sync itself with
the browser, but the hybrid listener may also schedule an additional
navigation. There are a few reasons this logic should not be included in
the Router:
* This special logic is not tree shakeable so it introduces a bundle
size cost for all applications, most of which don't need it.
* There have been many updates to the routing pipeline to tolerate
duplicate navigations. That is, duplicate navigations can happen and
routing should still complete successfully.
* https://github.com/angular/angular/commit/0e8548f667e5fdefa3ac7cdf1ba47e3e17011ffc
* https://github.com/angular/angular/commit/9e039ca68bfae5328f3fc1f16fabd7673c466a25
* The logic is really in the wrong place: The hybrid sync code should be
the location to handle this. If duplicate navigations are meant to be
avoided, the hybrid sync code should have handling to _not_ trigger
duplicate navs.
* This logic _also_ used to exist because the mock location
helper used for test incorrectly triggered popstate events during
router navigations. In order to avoid unexpected behavior in tests, this
logic needed to be added. This incorrect mocking may also have been
put in place because the upgrade module _would_ see a location change
event and trigger a duplicate navigation. The location mock has since been updated to
match real browser behavior so this is no longer necessary. The
upgrade module has also been updated to not trigger duplicate
navigations. The following commits are related to this:
* https://github.com/angular/angular/commit/202a1a56314af4ddb99c476f974536a10e390319
* https://github.com/angular/angular/commit/c6a93001eb74374b0fbc6aea1286fe1183d21382
Side note: The `setTimeout` in the location change listener is used to
ensure the ordering of duplicate navigations was consistent. You can see
that the logic being removed here expects the imperative navigation to precede the
popstate/hashchange. With the removal of this code, the `setTimeout` no
longer serves a purpose. However, it has been found that tests can rely
on this behavior (incorrectly) because they expect the navigation to be
complete but in reality, it hasn't even started because the test has not
flushed the timeout. Removing the timeout would be a breaking change as
a result.
PR Close#45240
The router used to wait for the resolvers to complete and take the last
value. The changes here take only the first
emitted value of every resolver and proceed the navigation. This matches
how other guards work in the `Router` code.
Resolves https://github.com/angular/angular/issues/44643
BREAKING CHANGE: Previously, resolvers were waiting to be completed
before proceeding with the navigation and the Router would take the last
value emitted from the resolver.
The router now takes only the first emitted value by the resolvers
and then proceeds with navigation. This is now consistent with `Observables`
returned by other guards: only the first value is used.
PR Close#44573
The `lastChild` property in the match result is only used to compute the
remaining segments (i.e. the ones which were not consumed). The updated
type here makes it easier to use and more clear.
PR Close#45170
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
The `should unregister a URL change listener` may fail in Firefox randomly because of
the `initialNavigation` being set to `true`. This may navigate to `/debug.html` and the
router throws an error `Cannot match any routes: 'debug.html'`.
PR Close#45171
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 various places in the repo (mostly tests/examples) to drop all `.ngfactory` and `.ngsummary` imports as they are no longer needed in Ivy.
PR Close#44957
BREAKING CHANGE: Forms [email] input coercion
Forms [email] input value will be considered as true if it is defined with any value rather
than false and 'false'.
PR Close#42803
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 code mimics behavior that Google Analytics has been using to
prevent duplicate navigations. They set up their own `HybridRoutingService`
location sync to avoid duplicate navigations that came from the Angular
router. This would happen because the Angular router would trigger a
navigation, which would then get picked up by the `$locationShim`, which
would trigger a `$locationChangeStart`, which would then be picked up by
the `setUpLocationSync` watcher here, which would again trigger a
navigation in the Angular Router.
All of this can be prevented by checking if the `navigationId` exists on
the history state object. This property is added by the Angular router
during navigations.
fixes#21610
PR Close#43441
This updates the router upgrade tests to use less mocked behavior. The
test upgrade location module is copied from the one that's used in the
common package. This update to the tests verifies more real behavior of
the upgrade module.
PR Close#43441
This commit provides a service, `PageTitleStrategy` for setting
the document page title after a successful router navigation.
Users can provide custom strategies by extending `TitleStrategy` and
adding a provider which overrides it.
The strategy takes advantage of the pre-existing `data` and `resolve` concepts
in the Router implementation:
We can copy the `Route.title` into `data`/`resolve` in a
non-breaking way by using a `symbol` as the key. This ensures that we
do not have any collisions with pre-existing property names. By using
`data` and `resolve`, we do not have to add anything more to
the router navigation pipeline to support this feature.
resolves#7630
PR Close#43307