Commit graph

730 commits

Author SHA1 Message Date
Andrew Kushnir
0d65e1de2c docs: declare Standalone APIs as stable (#47754)
In v14, we've introduced core concepts to allow Components, Directives and Pipes to configure their dependencies
 without the need to use NgModules and without the need to be declared in an NgModule. The concepts and initial
set of APIs were marked as "developer preview" to allow developers to use these APIs and share the feedback.

Since v14, we've been reviewing the entire API surface of the framework and either updating existing APIs to support standalone or creating new APIs that allowed to use Router, HttpClient and other abstractions without NgMod
ules.

Based on the mentioned work to review and stabilize APIs and also based on the positive feedback from the commun
ity, we are happy to announce that the Standalone APIs are promoted to stable!

This commit updates vast majority of standalone-related APIs to drop the `@developerPreview` label, which effect
ively documents then as stable.

Two APIs that retained the `@developerPreview` annotations are:
- withRequestsMadeViaParent (from `@angular/common/http`)
- renderApplication (from `@angular/platform-server`)

We plan to collect some additional feedback for the mentioned APIs and drop the `@developerPreview` annotation b
efore the next major release.

Co-Authored-By: Alex Rickabaugh <alx@alxandria.net>
Co-Authored-By: Andrew Scott <atscott@google.com>
Co-Authored-By: Dylan Hunn <dylhunn@gmail.com>
Co-Authored-By: Jessica Janiuk <jessicajaniuk@google.com>
Co-Authored-By: JoostK <joost.koehoorn@gmail.com>
Co-Authored-By: Kristiyan Kostadinov <crisbeto@abv.bg>
Co-Authored-By: Pawel Kozlowski <pkozlowski.opensource@gmail.com>

PR Close #47754
2022-10-17 12:15:20 +02:00
Alan Agius
1b9fd46d14 feat(core): add support for Node.js version 18 (#47730)
This change aligns with the supported Node.js versions of the Angular CLI.
See: https://github.com/angular/angular-cli/pull/24026

BREAKING CHANGE: Angular no longer supports Node.js versions `14.[15-19].x` and `16.[10-12].x`. Current supported versions of Node.js are `14.20.x`, `16.13.x` and `18.10.x`.

PR Close #47730
2022-10-11 17:21:19 +00:00
Andrew Kushnir
c0c7efaf7c feat(common): add provideLocationMocks() function to provide Location mocks (#47674)
This commit adds the `provideLocationMocks()` function that returns mocks for the `Location` and `LocationStrategy` classes. This function can be used in tests to configure an environment where it's possible to fire simulated location events (helpful when testing Router configuration).

PR Close #47674
2022-10-10 19:42:11 +00:00
Alex Rickabaugh
07017a7bd3 feat(router): prevent provideRouter() from usage in @Component (#47669)
This commit switches `provideRouter()` to return the new
`EnvironmentProviders` wrapper type, preventing it from being accidentally
(or intentionally) included in `@Component.providers`.

PR Close #47669
2022-10-07 14:03:13 -07:00
Alex Rickabaugh
7de1469be6 feat(core): introduce EnvironmentProviders wrapper type (#47669)
This commit introduces a new type `EnvironmentProviders` which can be used
in contexts where Angular accepted `Provider`s destined for
`EnvironmentInjector`s. This includes contexts such as `@NgModule.providers`
and `Route.providers`.

The new type is useful for preventing such providers from accidentally
ending up in `@Component.providers`. It can be used as the return type of
provider functions (such as `provideRouter`) to enforce this safety.

Because `Provider` allows `any[]` nested arrays, the compile-time safety
provided by `EnvironmentProviders` is easily circumvented. However, the
runtime shape of `EnvironmentProviders` is not compatible with component
injectors and will result in a runtime error if it leaks through (NG0207).

A new function `makeEnvironmentProviders` is used to construct this new type
from an array of providers.

The existing `importProvidersFrom` operation previously returned a very
similar type `ImportedNgModuleProviders` which had the same goal. This
machinery is switched over to use the new `EnvironmentProviders` interface
instead (in fact, `ImportedNgModuleProviders` is now just an alias to
`EnvironmentProviders`).

PR Close #47669
2022-10-07 14:03:13 -07:00
Andrew Kushnir
f73ef21442 feat(router): merge RouterLinkWithHref into RouterLink (#47630)
This commit updates the `RouterLink` to extend the selector to also include `<a>` and `<area>` elements, which were previously matched by the `RouterLinkWithHref` directive. The code of the directives was merged together (since there was a lot of duplication) and this commit finalizes the merge. The `RouterLinkWithHref` becomes an alias of the `RouterLink` directive.

Now there is no need to import and use the `RouterLinkWithHref` class, the `RouterLink` directive will match any element that has the `routerLink` attribute.

DEPRECATED:

The `RouterLinkWithHref` directive is deprecated, use the `RouterLink` directive instead. The `RouterLink` contains the code from the `RouterLinkWithHref` to handle elements with `href` attributes.

PR Close #47630
2022-10-05 15:16:43 -07:00
Andrew Scott
7b89d95c0e fix(router): Remove deprecated relativeLinkResolution (#47623)
The `relativeLinkResolution` is no longer supported. The only behavior
now is the correct behavior.

BREAKING CHANGE: `relativeLinkResolution` is no longer configurable in
the Router. This option was used as a means to opt out of a bug fix.

PR Close #47623
2022-10-05 08:57:28 -07:00
Andrew Kushnir
ab4ef264ed refactor(router): drop own constructor from the RouterLinkWithHref class (#47619)
This commit updates the `RouterLinkWithHref` class to further align with the `RouterLink` class by removing own constructor from the `RouterLinkWithHref` class.

PR Close #47619
2022-10-04 16:21:35 -07:00
Andrew Scott
2f0761000f test(router): Ensure change detection runs after navigation (#47629)
Components are not fully rendered until change detection runs.

PR Close #47629
2022-10-04 16:19:32 -07:00
Alex Rickabaugh
da58801f95 feat(router): auto-unwrap default exports when lazy loading (#47586)
When using `loadChildren` or `loadComponent`, a common pattern is to pass
a function that returns a `Promise` from a dynamic import:

```typescript
{
  path: 'lazy',
  loadComponent: () => import('./lazy-file').then(m => m.LazyCmp),
}
```

The `.then` part of the expression selects the particular exported
component symbol from the dynamically imported ES module.

ES modules can have a "default export", created with the `export default`
modifier:

```typescript
@Component({...})
export default class LazyCmp { ... }
```

This default export is made available to dynamic imports under the well-
known key of `'default'`, per the ES module spec:
https://tc39.es/ecma262/#table-export-forms-mapping-to-exportentry-records

This commit adds a feature to the router to automatically dereference such
default exports. With this logic, when `export default` is used, a `.then`
operation to select the particular exported symbol is no longer required:

```typescript
{
  path: 'lazy',
  loadComponent: () => import('./lazy-file'),
}
```

The above `loadComponent` operation will automatically use the `default`
export of the `lazy-file` ES module.

This functionality works for `loadChildren` as well.

PR Close #47586
2022-10-04 14:40:58 -07:00
Alex Rickabaugh
a2a066d325 refactor(router): organize deprecated loadChildren code (#47586)
This commit breaks out the code in @angular/router needed to support the
deprecated `loadChildren` signature into a separate file, which reduces the
opportunity for conflicts when patching that behavior in g3.

PR Close #47586
2022-10-04 14:40:58 -07:00
Andrew Scott
c3f857975d feat(router): make RouterOutlet name an Input so it can be set dynamically (#46569)
This commit updates the 'name' of `RouterOutlet` to be an `Input` rather
than an attribute. Note that this change does not affect `[attr.name]=`
because those already would not have worked. The static name was only
read in the constructor and if it wasn't available, it would use
'PRIMARY' instead.

fixes #12522

BREAKING CHANGE: Previously, the `RouterOutlet` would immediately
instantiate the component being activated during navigation. Now the
component is not instantiated until the change detection runs. This
could affect tests which do not trigger change detection after a router
navigation. In rarer cases, this can affect production code that relies
on the exact timing of component availability.

PR Close #46569
2022-10-04 07:57:25 -07:00
Andrew Kushnir
9eb38917fe refactor(router): apply href value via renderer to further align RouterLink directives (#47605)
This commit updates the `RouterLink` directive to use a renderer to apply an `href` attribute value. Previously, the `RouterLinkWithHref` used a host binding for this and that prevented further merge of the `RouterLink` and `RouterLinkWithHref` directives.

PR Close #47605
2022-10-03 08:45:46 -07:00
Andrew Kushnir
5a17858c5a refactor(router): unify the RouterLink and RouterLinkWithHref class logic (#47500)
Currently, the `RouterLink` and `RouterLinkWithHref` classes share a lot of common code (with some special logic around handling `<a>`-related scenarios). This commit unifies the logic of the mentioned directives by moving the necessary handling to the `RouterLink` directive and making it a parent one for the `RouterLinkWithHref` class (i.e. class RouterLinkWithHref extends RouterLink).

This is the first step in upcoming unification to merge both directives and just keep `RouterLink` one (it'd be done in followup PRs).

PR Close #47500
2022-09-29 10:48:39 -07:00
Andrew Scott
6a88bad019 fix(router): Ensure ActivatedRouteSnapshot#title has correct value (#47481)
ActivatedRouteSnapshot data gets mutated in the resolve phase of the Router. The title is assigned as part of this.
As a result, the title must be a getter in order to pick up the value that was note available during the class creation.

fixes #47459

BREAKING CHANGE: The title property is now required on ActivatedRouteSnapshot

PR Close #47481
2022-09-27 10:49:54 -07:00
Jeremy Elbourn
35f93bd409 refactor(router): remove unnecesary null (#47238)
These null values are unused and unecessary. I suspect it's a remnant from when the codebase was transpiled to Dart.

PR Close #47238
2022-09-06 09:57:37 -07:00
Andrew Scott
5163e3d876 feat(router): Add UrlTree constructor to public API (#47186)
The `UrlTree` is a fundamental concept in the router's API design.
Generally speaking, a `UrlTree` would be constructed via things like
`Router.createUrlTree` or `UrlSerializer#parse`. The second example here
is the core reason to make the constructor public, regardless of how
develpers generally create a `UrlTree` in an application.

Applications can provide their own `UrlSerializer` and may want to implement their
own `parse` method. This means they would also need to create a
`UrlTree` but would not be able to do so effectively because the
constructor is marked `@internal`.

In addition, the `UrlTree` constructor only has 3 parameters, all of
which are already public. There's nothing "special" about it other than
the potential desire to push developers to use other methods for
constructing a `UrlTree` (i.e. `Router.createUrlTree`).

Also see http://b/234604699#comment9 for additional context.

PR Close #47186
2022-08-22 10:44:52 -07:00
Andrew Scott
75df404467 feat(router): Create APIs for using Router without RouterModule (#47010)
This commit creates and exposes the APIs required to use the Angular Router without importing `RouterModule`.

The newly added APIs are tree-shakable and you can add features using special functions rather than using `ExtraOptions` to control the providers via an internal switch in Router code.

```
const appRoutes: Routes = [];
bootstrapApplication(AppComponent,
  {
    providers: [
      provideRouter(appRoutes,
        withDebugTracing(),     // enables debug tracing feature
        withInMemoryScrolling() // enables scrolling feature
    ]
  }
);
```

This "features" pattern allows for router behavior to evolve in a backwards compatible and tree-shakable way in the future. This approach also makes features more discoverable.

The newly added APIs can be used in any application today (doesn't require an application to be bootstrapped using standalone-based APIs).

Note: APIs added in this commit are released in the "Developer Preview" mode, read more about this mode in Angular docs: https://angular.io/guide/releases#developer-preview

PR Close #47010
2022-08-15 15:58:00 -07:00
Andrew Scott
d4f44bde50 refactor(router): Provide easily patchable file for assigning relativeLinkResolution (#47136)
For context on the migration plan, see b/241955063

PR Close #47136
2022-08-12 16:11:34 +00:00
Emmanuel Roux
422323cee0 feat(router): improve typings for RouterLink boolean inputs (#47101)
Add wider typings to setter of preserveFragment, skipLocationChange and replaceUrl inputs of routerLink directives and coerce them to boolean

PR Close #47101
2022-08-12 13:28:38 +00:00
Andrew Scott
93289f9c76 refactor(router): Update error message when Router is provided twice (#47130)
The current error message is absolute in that it thinks there is only
one possible way to provide Router twice. In fact, you can get a new
instance of the Router in several ways so the error message should
indicate the exact failure case with a _potential_ cause.

Based on findings in thread 0cbbd6aeec (commitcomment-80900192)

PR Close #47130
2022-08-12 13:27:49 +00:00
Andrew Scott
2a43beec15 fix(router): Fix route recognition behavior with some versions of rxjs (#47098)
Some versions of rxjs cause the algorithm used in the Router to not recognize Route configs correctly.
This commit updates the algorithm to be compatible in the same way as other code locations internally.

Context:
1160b8194f

fixes #47089

Note: This does not have a test because I was unable to identify the
version of rxjs that would cause a failure here.

PR Close #47098
2022-08-10 09:25:06 -07:00
Andrew Scott
0abb67af59 feat(router): allow guards and resolvers to be plain functions (#46684)
The current Router APIs require guards/resolvers to be present in the DI tree. This is because we want to treat all guards/resolvers equally and some may require dependencies. This requirement results in quite a lot of boilerplate for guards. Here are two examples:

```
const MY_GUARD = new InjectionToken<any>('my_guard');
…
providers: {provide: MY_GUARD, useValue: () => window.someGlobalState}
…
const route = {path: 'somePath', canActivate: [MY_GUARD]}
```

```
@Injectable({providedIn: 'root'})
export class MyGuardWithDependency {
  constructor(private myDep: MyDependency) {}

  canActivate() {
    return myDep.canActivate();
  }
}
…
const route = {path: 'somePath', canActivate: [MyGuardWithDependency]}
```

Notice that even when we want to write a simple guard that has no dependencies as in the first example, we still have to write either an InjectionToken or an Injectable class.

With this commit router guards and resolvers can be plain old functions.
 For example:

```
const route = {path: 'somePath', component: EditCmp, canDeactivate: [(component: EditCmp) => !component.hasUnsavedChanges]}
```

Additionally, these functions can still use Angular DI with `inject` from `@angular/core`.

```
const route = {path: 'somePath', canActivate: [() => inject(MyDependency).canActivate()]}
```

PR Close #46684
2022-08-05 10:36:46 -07:00
Andrew Scott
d8cf78ba5e fix(router): Do not call preload method when not necessary (#47007)
In Angular 14, we introduced the `loadComponent` API for a `Route` to
allow lazy loading of a routed component in addition to the existing
`loadChildren` which allows lazy loading of child routes. As a result,
the `preload` method of the `PreloadingStrategy` needs to sometimes be
called even when there is a `canLoad` guard on the `Route`. `CanLoad`
guards block loading of child routes but _do not_ block loading of the
component.

This change updates the conditional checks in the internal preloader to
skip calling the `PreloadingStrategy.preload` when there is only a
`loadChildren` callback with a `canLoad` guard an no `loadComponent`.
In this case, the callback passed to the `preload` method is already
effectively a no-op so it's not necessary to call it at all.

resolves #47003

PR Close #47007
2022-08-02 09:38:28 -07:00
Andrew Scott
f364378e4d fix(router): Use correct return type for provideRoutes function (#46941)
The provideRoutes function of the Router returns a Provider array and should not be typed as 'any'

PR Close #46941
2022-08-01 11:20:49 -07:00
Andrew Scott
8600732b09 feat(router): Expose the default matcher for Routes used by the Router (#46913)
This commit adds the `defaultUrlMatcher` from the Router to the public
API. `UrlMatcher` and `UrlMatchResult` are already in the public api so
the signature of the function as well as the return value are already
exposed. Any change to those or the implementation of `defaultUrlMatcher`
would already be breaking so there's no additional risk in exposing the
default matcher.

This function can be useful for developers who want to create a custom
matcher which builds on the default matcher of the Router. Currently,
the only way to do this would be to copy-paste the implementation.

fixes #35928

PR Close #46913
2022-08-01 11:19:33 -07:00
Andrew Scott
55febc1691 refactor(router): Remove unused ANALYZE_FOR_ENTRY_COMPONENTS (#46942)
`entryComponents` is a feature that is not used or necessary in Angular
anymore.

PR Close #46942
2022-08-01 11:18:09 -07:00
Alan Agius
f4348360a6 docs(router): remove incorrect deprecation text in InitialNavigation (#46916)
Remove left over deprecation note.

PR Close #46916
2022-07-22 08:26:25 +00:00
Andrew Scott
8ac45a6264 refactor(router): Update internal INITIAL_NAVIGATION token to use an enum (#46925)
This updates the internal use of INITIAL_NAVIGATION to do two things:

1. Explicitly provide `Enabled` as the default for the token factory
2. Use an enum instead of a string to reduce bundle size

PR Close #46925
2022-07-22 08:25:37 +00:00
Emmanuel Roux
10289f1f6e feat(router): expose resolved route title (#46826)
Expose resolved route title from ActivatedRoute and ActivatedRouteSnapshot

PR Close #46826
2022-07-21 09:24:56 +00:00
Andrew Scott
d583f85701 refactor(router): Update Router to be providedIn: 'root' (#46824)
This commit updates the Router itself to be `providedIn: 'root'` with a
factory function rather than provided in the `RouterModule`.

PR Close #46824
2022-07-20 11:36:04 -07:00
Andrew Kushnir
7a6509bdc1 refactor(core): NgModuleRef should not implement EnvironmentInjector interface (#46896)
This commit refactors the `NgModuleRef` implementation to drop functions required by the `EnvironmentInjector` interface. Previously the idea was that the `NgModuleRef` can act as an Injector to facilitate easier transition to standalone. However, from the mental model perspective, the `NgModuleRef` has the `injector` field, which is the correct injector reference and can be used is needed as an `EnvironmentInjector`.

PR Close #46896
2022-07-20 08:49:15 -07:00
Andrew Scott
bde925bd42 refactor(router): Update TitleStrategy to useFactory (#46876)
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
2022-07-18 22:02:18 +00:00
Paul Gschwendtner
d2b444a8a2 test: update tests to account for karma-jasmine v5.0.0
Karma jasmine updated the `jasmine-core` dependency. Jasmine is now more
strict when:

* The done callback is invoked multiple times
* The done callback is used, while a promise is also returned
* The done callback is treated as error when e.g. a number is returned
  as first argument. This was the case with `requestAnimationFrame`.
2022-07-18 19:19:00 +02:00
Andrew Scott
c0f023f602 fix(router): Ensure target RouterStateSnapshot is defined in NavigationError (#46842)
The Router transition observable pipe keeps an outer reference to a `t`
variable for use in the `catchError` operator. However, this variable is
not updated with intermediate state. This commit fixes that so the
`catchError` can access properties that get updated in intermediate
states. Specifically, `RouterStateSnapshot` in the `NavigationError` for
now but could be more in the future.

PR Close #46842
2022-07-14 22:19:26 +00:00
Andrew Scott
26ea97688c feat(router): Make router directives standalone (#46758)
This commit makes the router directives standalone and refactors some of
the Router injectables to be `providedIn: 'root'` along with factory
functions for initialization.

PR Close #46758
2022-07-14 21:11:14 +00:00
Jessica Janiuk
9ad296a55f Revert "refactor(router): Remove use of OutletInjector" (#46775)
This reverts commit e288d87742.

PR Close #46775
2022-07-11 19:13:20 +00:00
Andrew Scott
bf5bee6d43 refactor(router): move around some code to eliminate circular deps (#46752)
This commit eliminates some circular dependencies by moving around
interfaces and type guards.

PR Close #46752
2022-07-11 17:59:31 +00:00
Andrew Scott
e8ae0fe3e9 fix(router): Fix cancellation code for canLoad rejections (#46752)
Before this commit, the `NavigationCancellationCode` would always be set
to `Redirect` when encountering a "navigationcancelingError". However,
this error can also be thrown when `CanLoad` guars reject. This commit
ensures these cancellation errors have a code as well so this mistake
cannot be made again.

PR Close #46752
2022-07-11 17:59:30 +00:00
Andrew Scott
647afb02b3 refactor(router): Simplify the prioritizeGuardValue logic (#46745)
The existing logic does something similar but in a more roundabout way.
It reads _the whole array_. If it encounters a pending value, it ignores
the remaining ones. If it hasn't encountered a pending value by the time
it hits false/UrlTree, it returns that result.

The new logic is the same, but reverses what we're looking for. Instead
of processing the whole array, we stop when we encounter an initial
value. When we encounter one that isn't `true`, that gets returned. If
we get to the end and everything was `true`, return `true`.

PR Close #46745

PR Close #46745
2022-07-11 16:55:58 +00:00
Jessica Janiuk
a003dd8dc2 Revert "refactor(router): Simplify the prioritizeGuardValue logic" (#46759)
This reverts commit f32fface4763d789a8b7cc4f4489f98be4e1073a.

PR Close #46759
2022-07-08 22:27:01 +00:00
Andrew Scott
9acec3f0f7 refactor(router): Remove use of OutletInjector (#46755)
OutletInjector doesn't do anything special. Injector.create can be used instead

PR Close #46755
2022-07-08 21:56:01 +00:00
John Vandenberg
c14c701775 docs: fix spelling (#46713)
PR Close #46713
2022-07-08 20:54:52 +00:00
Andrew Scott
cee207ea11 refactor(router): Simplify the prioritizeGuardValue logic (#46745)
The existing logic does something similar but in a more roundabout way.
It reads _the whole array_. If it encounters a pending value, it ignores
the remaining ones. If it hasn't encountered a pending value by the time
it hits false/UrlTree, it returns that result.

The new logic is the same, but reverses what we're looking for. Instead
of processing the whole array, we stop when we encounter an initial
value. When we encounter one that isn't `true`, that gets returned. If
we get to the end and everything was `true`, return `true`.

PR Close #46745
2022-07-08 20:03:47 +00:00
Andrew Scott
a4ce273e50 feat(router): Add the target RouterStateSnapshot to NavigationError (#46731)
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
2022-07-08 16:19:06 +00:00
Andrew Scott
6c1357dd7d feat(router): Add stable cancelation code to NavigationCancel event (#46675)
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
2022-07-06 07:42:24 -07:00
Andrew Scott
dd3e0968ec refactor(router): Remove custom error message for invalid guards (#46678)
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
2022-07-01 13:25:50 -07:00
Andrew Scott
ee2e4917e6 docs: Update runGuardsAndResolvers documentation (#46671)
fixes  #46001

PR Close #46671
2022-07-01 10:19:22 -07:00
Andrew Scott
e8c7dd10e9 fix(router): Ensure APP_INITIALIZER of enabledBlocking option completes (#46026)
Previously, if `initialNavigation` were set to `enabledBlocking`, the
Router's `APP_INITIALIZER` would never resolve if that initial
navigation failed. This results in the application load hanging and
never completing.

fixes #44355

PR Close #46026
2022-06-29 14:53:30 -07:00
Andrew Scott
36f46c6a9d refactor(router): Convert user-visible router errors to RuntimeError (#46562)
This commit refactors the Router errors to use the standard
`RuntimeError` used by the framework packages.

PR Close #46562
2022-06-29 12:50:23 -07:00