mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 99723fc64e | |||
| 6a8ea29a04 | |||
| caf7228f8a | |||
| 896c04fac4 | |||
| 772ddc1baa | |||
| 9e013d3dd7 | |||
| 9770964acf | |||
| 8d251fc0cf | |||
| f112f8d211 | |||
| 1c1c4555a2 | |||
| 057e495db5 | |||
| b86c6a8909 | |||
| 783d21431f | |||
| 2ffa34eebc | |||
| e615b598ba | |||
| 6ce7d76a0e | |||
| 8aa8b4b77c | |||
| 61fc47475d | |||
| 3fe75710d9 | |||
| b09a716e80 | |||
| b3d0a2717e | |||
| f672d8fa46 | |||
| a8ba26561b | |||
| d832cb2e23 | |||
| 23b465e5ed | |||
| d7d23b0320 | |||
| 28ea114d54 |
+63
-115
@@ -1,24 +1,77 @@
|
||||
<a name="15.1.0-next.3"></a>
|
||||
# 15.1.0-next.3 (2022-12-14)
|
||||
### animations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [c86484507f](https://github.com/angular/angular/commit/c86484507fdc0a44b3d20ea8b988b23f25ad9ac2) | fix | fix incorrect handling of camel-case css properties ([#48436](https://github.com/angular/angular/pull/48436)) |
|
||||
<a name="15.1.0"></a>
|
||||
# 15.1.0 (2023-01-10)
|
||||
## Deprecations
|
||||
### router
|
||||
* `CanLoad` guards in the Router are deprecated. Use `CanMatch`
|
||||
instead.
|
||||
|
||||
* None of the public properties of the Router are meant to be writeable. They should all be configured using other methods, all of which have been documented:
|
||||
|
||||
The following strategies are meant to be configured by registering the
|
||||
application strategy in DI via the `providers` in the root `NgModule` or
|
||||
`bootstrapApplication`:
|
||||
* `routeReuseStrategy`
|
||||
* `titleStrategy`
|
||||
* `urlHandlingStrategy`
|
||||
|
||||
The following options are meant to be configured using the options
|
||||
available in `RouterModule.forRoot` or `provideRouter`.
|
||||
* `onSameUrlNavigation`
|
||||
* `paramsInheritanceStrategy`
|
||||
* `urlUpdateStrategy`
|
||||
* `canceledNavigationResolution`
|
||||
|
||||
The following options are available in `RouterModule.forRoot` but not
|
||||
available in `provideRouter`:
|
||||
* `malformedUriErrorHandler` - This was found to not be used anywhere
|
||||
internally.
|
||||
* `errorHandler` - Developers can instead subscribe to `Router.events`
|
||||
and filter for `NavigationError`.
|
||||
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [fe50813664](https://github.com/angular/angular/commit/fe50813664809a1177132a77bd2a316ad0858b9e) | feat | Add BrowserPlatformLocation to the public API ([#48488](https://github.com/angular/angular/pull/48488)) |
|
||||
| [e362214924](https://github.com/angular/angular/commit/e362214924dbb784e5bd0efd96530134f8c91d32) | fix | Fix TestBed.overrideProvider type to include multi ([#48424](https://github.com/angular/angular/pull/48424)) |
|
||||
### compiler-cli
|
||||
| [2f4f0638c7](https://github.com/angular/angular/commit/2f4f0638c74dccfc2d0522f67ab226d3227c0566) | fix | Add data attribtue to NgOptimizedImage ([#48497](https://github.com/angular/angular/pull/48497)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a6849f27af](https://github.com/angular/angular/commit/a6849f27af129588091f635c6ae7a326241344fc) | fix | evaluate const tuple types statically ([#48091](https://github.com/angular/angular/pull/48091)) |
|
||||
| [a532d71975](https://github.com/angular/angular/commit/a532d71975bef463223fd5d8322e3140760c9134) | feat | allow self-closing tags on custom elements ([#48535](https://github.com/angular/angular/pull/48535)) |
|
||||
| [33f35b04ef](https://github.com/angular/angular/commit/33f35b04ef0f32f25624a6be59f8635675e3e131) | fix | type-only symbols incorrectly retained when downlevelling custom decorators ([#48638](https://github.com/angular/angular/pull/48638)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6acae1477a](https://github.com/angular/angular/commit/6acae1477a212bbd85d0670913c2925fa3bc0c24) | feat | Add `TestBed.runInInjectionContext` to help test functions which use `inject` ([#47955](https://github.com/angular/angular/pull/47955)) |
|
||||
| [38421578a2](https://github.com/angular/angular/commit/38421578a2573bcbc86c927ed4015e20fc39f04a) | feat | Make the `isStandalone()` function available in public API ([#48114](https://github.com/angular/angular/pull/48114)) |
|
||||
| [dd42974b07](https://github.com/angular/angular/commit/dd42974b070b068135c1bc34072486ae440e45e0) | feat | support TypeScript 4.9 ([#48005](https://github.com/angular/angular/pull/48005)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8aa8b4b77c](https://github.com/angular/angular/commit/8aa8b4b77cefcdd400ec9767b946b295ef42a066) | fix | Form provider FormsModule.withConfig return a FormsModule ([#48526](https://github.com/angular/angular/pull/48526)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5f0b53c735](https://github.com/angular/angular/commit/5f0b53c7352f19480185c6b5c769e5012a2d2faa) | feat | Allow auto-imports to suggest multiple possible imports. ([#47787](https://github.com/angular/angular/pull/47787)) |
|
||||
| [ce8160ecb2](https://github.com/angular/angular/commit/ce8160ecb28d6765d438eb65035835984eb956ec) | fix | Prevent crashes on unemitable references ([#47938](https://github.com/angular/angular/pull/47938)) |
|
||||
### localize
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [a1a8e91eca](https://github.com/angular/angular/commit/a1a8e91ecaded6a2e4d700109a26d3117ad77c9c) | fix | add triple slash type reference on `@angular/localize` on `ng add ([#48502](https://github.com/angular/angular/pull/48502)) |
|
||||
### migrations
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [cc284afbbc](https://github.com/angular/angular/commit/cc284afbbc33b91884882204c5958a44a5d11392) | fix | combine newly-added imports in import manager ([#48620](https://github.com/angular/angular/pull/48620)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [228e992db7](https://github.com/angular/angular/commit/228e992db75bd7a2213b4596e6e2a8696578aa19) | docs | Deprecate canLoad guards in favor of canMatch ([#48180](https://github.com/angular/angular/pull/48180)) |
|
||||
| [0a8b8a66cd](https://github.com/angular/angular/commit/0a8b8a66cdfb86586811c79bec938b3ab7215e8f) | docs | Deprecate public members of Router that are meant to be configured elsewhere ([#48006](https://github.com/angular/angular/pull/48006)) |
|
||||
| [332461bd0c](https://github.com/angular/angular/commit/332461bd0c5f5734a9d7f051f0f4c6c173dd87c9) | feat | Add ability to override `onSameUrlNavigation` default per-navigation ([#48050](https://github.com/angular/angular/pull/48050)) |
|
||||
| [f58ad86e51](https://github.com/angular/angular/commit/f58ad86e51817f83ff18db790a347528262b850b) | feat | Add feature provider for enabling hash navigation ([#48301](https://github.com/angular/angular/pull/48301)) |
|
||||
| [73f03ad2d2](https://github.com/angular/angular/commit/73f03ad2d29811dda2ee03c5f18c79ebc9519c0b) | feat | Add new NavigationSkipped event for ignored navigations ([#48024](https://github.com/angular/angular/pull/48024)) |
|
||||
| [3fe75710d9](https://github.com/angular/angular/commit/3fe75710d97a0f3224b2b09c45d9b8a9ad6efe91) | fix | page refresh should not destroy history state ([#48540](https://github.com/angular/angular/pull/48540)) |
|
||||
## Special Thanks
|
||||
Alan Agius, Andrew Kushnir, Andrew Scott, Aristeidis Bampakos, Bob Watson, BrowserPerson, Jens, Jessica Janiuk, Joey Perrott, JoostK, Konstantin Kharitonov, Lukas Matta, Matthieu Riegler, Piotr Kowalski, Virginia Dooley, Yannick Baron, dario-piotrowicz, lsst25, piyush132000 and why520crazy
|
||||
Alan Agius, Alex Castle, Alex Rickabaugh, Andrew Kushnir, Andrew Scott, Bob Watson, Charles Lyding, Derek Cormier, Doug Parker, Dylan Hunn, George Kalpakas, Greg Magolan, Jessica Janiuk, JiaLiPassion, Joey Perrott, Kristiyan Kostadinov, Matthieu Riegler, Paul Gschwendtner, Pawel Kozlowski, Renan Ferro, Tim Gates, Vadim, Virginia Dooley, ced, mgechev, piyush132000, robertIsaac and sr5434
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
@@ -41,32 +94,6 @@ Alan Agius, Andrew Kushnir, Andrew Scott, Aristeidis Bampakos, Bob Watson, Brows
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="15.1.0-next.2"></a>
|
||||
# 15.1.0-next.2 (2022-12-07)
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [8e52ca2714](https://github.com/angular/angular/commit/8e52ca271496b0feebf66b2dc7c8f396b73d61a0) | fix | Don't generate srcsets with very large sources ([#47997](https://github.com/angular/angular/pull/47997)) |
|
||||
| [f8ecc194e9](https://github.com/angular/angular/commit/f8ecc194e93bf9f80af0cb0e77032341bf2f9886) | fix | Update `Location` to support base href containing `origin` ([#48327](https://github.com/angular/angular/pull/48327)) |
|
||||
### compiler
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [4c023956d8](https://github.com/angular/angular/commit/4c023956d8dd05d8455612dff185a7e7918c9fed) | fix | make sure selectors inside container queries are correctly scoped ([#48353](https://github.com/angular/angular/pull/48353)) |
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [27eaded62d](https://github.com/angular/angular/commit/27eaded62dbe059fc9ac02cfa7f53ccf8aebccbf) | fix | Produce diagnostic rather than crash when using invalid hostDirective ([#48314](https://github.com/angular/angular/pull/48314)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [38421578a2](https://github.com/angular/angular/commit/38421578a2573bcbc86c927ed4015e20fc39f04a) | feat | Make the `isStandalone()` function available in public API ([#48114](https://github.com/angular/angular/pull/48114)) |
|
||||
| [dd42974b07](https://github.com/angular/angular/commit/dd42974b070b068135c1bc34072486ae440e45e0) | feat | support TypeScript 4.9 ([#48005](https://github.com/angular/angular/pull/48005)) |
|
||||
| [5f9c7ceb90](https://github.com/angular/angular/commit/5f9c7ceb907be47dff3e203dd837fd6ee9133fcb) | fix | unable to inject ChangeDetectorRef inside host directives ([#48355](https://github.com/angular/angular/pull/48355)) |
|
||||
## Special Thanks
|
||||
Alan Agius, Alex Castle, Andrew Kushnir, Andrew Scott, Bob Watson, Charles Lyding, Derek Cormier, Joey Perrott, Konstantin Kharitonov, Kristiyan Kostadinov, Matthieu Riegler, Paul Gschwendtner, Pawel Kozlowski, dario-piotrowicz, piyush132000 and sr5434
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="15.0.3"></a>
|
||||
# 15.0.3 (2022-12-07)
|
||||
### common
|
||||
@@ -91,26 +118,6 @@ Alan Agius, Alex Castle, Andrew Kushnir, Andrew Scott, Bob Watson, Derek Cormier
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="15.1.0-next.1"></a>
|
||||
# 15.1.0-next.1 (2022-11-30)
|
||||
## Deprecations
|
||||
### router
|
||||
- CanLoad guards in the Router are deprecated. Use CanMatch
|
||||
instead.
|
||||
### compiler-cli
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [7d88700933](https://github.com/angular/angular/commit/7d8870093313575d89c8abe584c43d6fa8105fc8) | fix | accept inheriting the constructor from a class in a library ([#48156](https://github.com/angular/angular/pull/48156)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [228e992db7](https://github.com/angular/angular/commit/228e992db75bd7a2213b4596e6e2a8696578aa19) | docs | Deprecate canLoad guards in favor of canMatch ([#48180](https://github.com/angular/angular/pull/48180)) |
|
||||
| [332461bd0c](https://github.com/angular/angular/commit/332461bd0c5f5734a9d7f051f0f4c6c173dd87c9) | feat | Add ability to override `onSameUrlNavigation` default per-navigation ([#48050](https://github.com/angular/angular/pull/48050)) |
|
||||
## Special Thanks
|
||||
Alan Agius, Andrew Scott, Aristeidis Bampakos, Bob Watson, Derek Cormier, Dylan Hunn, JoostK, Kristiyan Kostadinov, Matthieu Riegler, Paul Gschwendtner, Pawel Kozlowski, Rokas Brazdžionis and piyush132000
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="15.0.2"></a>
|
||||
# 15.0.2 (2022-11-30)
|
||||
### compiler-cli
|
||||
@@ -149,65 +156,6 @@ Alan Agius, Andrew Scott, Bjarki, Bob Watson, Brooke, Derek Cormier, Dylan Hunn,
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="15.1.0-next.0"></a>
|
||||
# 15.1.0-next.0 (2022-11-22)
|
||||
## Deprecations
|
||||
### router
|
||||
- router writable properties
|
||||
|
||||
The following strategies are meant to be configured by registering the
|
||||
application strategy in DI via the `providers` in the root `NgModule` or
|
||||
`bootstrapApplication`:
|
||||
* `routeReuseStrategy`
|
||||
* `titleStrategy`
|
||||
* `urlHandlingStrategy`
|
||||
|
||||
The following options are meant to be configured using the options
|
||||
available in `RouterModule.forRoot` or `provideRouter`.
|
||||
* `onSameUrlNavigation`
|
||||
* `paramsInheritanceStrategy`
|
||||
* `urlUpdateStrategy`
|
||||
* `canceledNavigationResolution`
|
||||
|
||||
The following options are available in `RouterModule.forRoot` but not
|
||||
available in `provideRouter`:
|
||||
* `malformedUriErrorHandler` - This was found to not be used anywhere
|
||||
internally.
|
||||
* `errorHandler` - Developers can instead subscribe to `Router.events`
|
||||
and filter for `NavigationError`.
|
||||
### common
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [b0a62bea47](https://github.com/angular/angular/commit/b0a62bea475480768f2cffeb134960dc1165181c) | fix | Fix MockPlatformLocation events and missing onPopState implementation ([#48113](https://github.com/angular/angular/pull/48113)) |
|
||||
### core
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [6acae1477a](https://github.com/angular/angular/commit/6acae1477a212bbd85d0670913c2925fa3bc0c24) | feat | Add `TestBed.runInInjectionContext` to help test functions which use `inject` ([#47955](https://github.com/angular/angular/pull/47955)) |
|
||||
### forms
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [0329c13e95](https://github.com/angular/angular/commit/0329c13e95127fd6f0044b6809b9bccb27f3cb91) | fix | don't mutate validators array ([#47830](https://github.com/angular/angular/pull/47830)) |
|
||||
| [d321880440](https://github.com/angular/angular/commit/d3218804401fb35d8da1de91960bbdf9ab0aa823) | fix | FormBuilder.group return right type with shorthand parameters. ([#48084](https://github.com/angular/angular/pull/48084)) |
|
||||
### language-service
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [5f0b53c735](https://github.com/angular/angular/commit/5f0b53c7352f19480185c6b5c769e5012a2d2faa) | feat | Allow auto-imports to suggest multiple possible imports. ([#47787](https://github.com/angular/angular/pull/47787)) |
|
||||
| [fd2eea5961](https://github.com/angular/angular/commit/fd2eea59613ab3cdde871046b6086216d77a386e) | fix | correctly handle host directive inputs/outputs ([#48147](https://github.com/angular/angular/pull/48147)) |
|
||||
| [ce8160ecb2](https://github.com/angular/angular/commit/ce8160ecb28d6765d438eb65035835984eb956ec) | fix | Prevent crashes on unemitable references ([#47938](https://github.com/angular/angular/pull/47938)) |
|
||||
| [764fa3d9c3](https://github.com/angular/angular/commit/764fa3d9c37eb70acd21879296ec039de07173ea) | fix | update packages/language-service/build.sh script to work with vscode-ng-language-service's new Bazel build ([#48120](https://github.com/angular/angular/pull/48120)) |
|
||||
### router
|
||||
| Commit | Type | Description |
|
||||
| -- | -- | -- |
|
||||
| [0a8b8a66cd](https://github.com/angular/angular/commit/0a8b8a66cdfb86586811c79bec938b3ab7215e8f) | docs | Deprecate public members of Router that are meant to be configured elsewhere ([#48006](https://github.com/angular/angular/pull/48006)) |
|
||||
| [73f03ad2d2](https://github.com/angular/angular/commit/73f03ad2d29811dda2ee03c5f18c79ebc9519c0b) | feat | Add new NavigationSkipped event for ignored navigations ([#48024](https://github.com/angular/angular/pull/48024)) |
|
||||
| [b51929a394](https://github.com/angular/angular/commit/b51929a394acaa129699bc72e34882b7e577dd7f) | fix | correct type of nextState parameter in canDeactivate ([#48038](https://github.com/angular/angular/pull/48038)) |
|
||||
| [1df0ed7d6e](https://github.com/angular/angular/commit/1df0ed7d6e636d921ad617465c3956dc1b6292eb) | fix | Ensure renavigating in component init works with enabledBlocking ([#48063](https://github.com/angular/angular/pull/48063)) |
|
||||
| [1976e37475](https://github.com/angular/angular/commit/1976e37475e144d4df27b1558b2acd929bd439be) | fix | restore 'history.state' on popstate even if navigationId missing ([#48033](https://github.com/angular/angular/pull/48033)) |
|
||||
## Special Thanks
|
||||
Alan Agius, Andrew Kushnir, Andrew Scott, Bjarki, Bob Watson, Brooke, Derek Cormier, Dylan Hunn, George Kalpakas, Greg Magolan, Ikko Ashimine, Ivan Rodriguez, Jessica Janiuk, JiaLiPassion, Joe Roxbury, Joey Perrott, Kristiyan Kostadinov, Matthieu Riegler, Mikhail Savchuk, Nebojsa Cvetkovic, Pawel Kozlowski, Volodymyr, Wooshaah and mgechev
|
||||
|
||||
<!-- CHANGELOG SPLIT MARKER -->
|
||||
|
||||
<a name="12.2.17"></a>
|
||||
# 12.2.17 (2022-11-22)
|
||||
## Breaking Changes
|
||||
|
||||
@@ -7,7 +7,7 @@ import { Component, OnInit, Input } from '@angular/core';
|
||||
templateUrl: './item-detail.component.html',
|
||||
styleUrls: ['./item-detail.component.css']
|
||||
})
|
||||
export class ItemDetailComponent implements OnInit {
|
||||
export class ItemDetailComponent {
|
||||
|
||||
// #docregion input-type
|
||||
@Input() childItem = '';
|
||||
@@ -18,9 +18,4 @@ export class ItemDetailComponent implements OnInit {
|
||||
|
||||
currentItem = 'bananas in boxes';
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,6 +12,5 @@ export class ItemListComponent {
|
||||
// #docregion item-input
|
||||
@Input() items: Item[] = [];
|
||||
// #enddocregion item-input
|
||||
constructor() { }
|
||||
|
||||
}
|
||||
|
||||
+1
-4
@@ -3,7 +3,4 @@ import { Injectable } from '@angular/core';
|
||||
@Injectable({
|
||||
providedIn: 'root'
|
||||
})
|
||||
export class MyLibService {
|
||||
|
||||
constructor() { }
|
||||
}
|
||||
export class MyLibService {}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// #docplaster
|
||||
// #docregion, v1
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
// #enddocregion v1
|
||||
import { Hero } from '../hero';
|
||||
// #docregion v1
|
||||
@@ -10,7 +10,7 @@ import { Hero } from '../hero';
|
||||
templateUrl: './heroes.component.html',
|
||||
styleUrls: ['./heroes.component.css']
|
||||
})
|
||||
export class HeroesComponent implements OnInit {
|
||||
export class HeroesComponent {
|
||||
// #enddocregion, v1
|
||||
/*
|
||||
// #docregion add-hero
|
||||
@@ -23,11 +23,5 @@ export class HeroesComponent implements OnInit {
|
||||
name: 'Windstorm'
|
||||
};
|
||||
// #docregion v1
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
||||
// #enddocregion, v1
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { Hero } from '../hero';
|
||||
// #docregion import-heroes
|
||||
import { HEROES } from '../mock-heroes';
|
||||
@@ -14,7 +14,7 @@ import { HEROES } from '../mock-heroes';
|
||||
// #enddocregion metadata
|
||||
|
||||
// #docregion component
|
||||
export class HeroesComponent implements OnInit {
|
||||
export class HeroesComponent {
|
||||
|
||||
heroes = HEROES;
|
||||
// #enddocregion component
|
||||
@@ -22,11 +22,6 @@ export class HeroesComponent implements OnInit {
|
||||
selectedHero?: Hero;
|
||||
// #enddocregion on-select
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
// #docregion on-select
|
||||
onSelect(hero: Hero): void {
|
||||
this.selectedHero = hero;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
// #docregion
|
||||
// #docregion import-input
|
||||
import { Component, OnInit, Input } from '@angular/core';
|
||||
import { Component, Input } from '@angular/core';
|
||||
// #enddocregion import-input
|
||||
// #docregion import-hero
|
||||
import { Hero } from '../hero';
|
||||
@@ -11,14 +11,8 @@ import { Hero } from '../hero';
|
||||
templateUrl: './hero-detail.component.html',
|
||||
styleUrls: ['./hero-detail.component.css']
|
||||
})
|
||||
export class HeroDetailComponent implements OnInit {
|
||||
export class HeroDetailComponent {
|
||||
// #docregion input-hero
|
||||
@Input() hero?: Hero;
|
||||
// #enddocregion input-hero
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit(): void {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// #docregion
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
// #docregion import-message-service
|
||||
import { MessageService } from '../message.service';
|
||||
// #enddocregion import-message-service
|
||||
@@ -9,13 +9,10 @@ import { MessageService } from '../message.service';
|
||||
templateUrl: './messages.component.html',
|
||||
styleUrls: ['./messages.component.css']
|
||||
})
|
||||
export class MessagesComponent implements OnInit {
|
||||
export class MessagesComponent {
|
||||
|
||||
// #docregion ctor
|
||||
constructor(public messageService: MessageService) {}
|
||||
// #enddocregion ctor
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { MessageService } from '../message.service';
|
||||
|
||||
@Component({
|
||||
@@ -6,11 +6,8 @@ import { MessageService } from '../message.service';
|
||||
templateUrl: './messages.component.html',
|
||||
styleUrls: ['./messages.component.css']
|
||||
})
|
||||
export class MessagesComponent implements OnInit {
|
||||
export class MessagesComponent {
|
||||
|
||||
constructor(public messageService: MessageService) {}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
import { MessageService } from '../message.service';
|
||||
|
||||
@Component({
|
||||
@@ -6,11 +6,8 @@ import { MessageService } from '../message.service';
|
||||
templateUrl: './messages.component.html',
|
||||
styleUrls: ['./messages.component.css']
|
||||
})
|
||||
export class MessagesComponent implements OnInit {
|
||||
export class MessagesComponent {
|
||||
|
||||
constructor(public messageService: MessageService) {}
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ import { Component } from '@angular/core';
|
||||
styleUrls: ['./app.component.css']
|
||||
})
|
||||
export class AppComponent {
|
||||
constructor() { }
|
||||
// #docregion font-size
|
||||
fontSizePx = 16;
|
||||
// #enddocregion font-size
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
import 'zone.js/node';
|
||||
|
||||
import { APP_BASE_HREF } from '@angular/common';
|
||||
import { ngExpressEngine } from '@nguniversal/express-engine';
|
||||
import * as express from 'express';
|
||||
import { existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
import { AppServerModule } from './src/main.server';
|
||||
import { APP_BASE_HREF } from '@angular/common';
|
||||
import { existsSync } from 'fs';
|
||||
|
||||
// The Express app is exported so that it can be used by serverless Functions.
|
||||
export function app() {
|
||||
export function app(): express.Express {
|
||||
const server = express();
|
||||
const distFolder = join(process.cwd(), 'dist/browser');
|
||||
const indexHtml = existsSync(join(distFolder, 'index.original.html')) ? 'index.original.html' : 'index';
|
||||
@@ -48,8 +48,8 @@ export function app() {
|
||||
return server;
|
||||
}
|
||||
|
||||
function run() {
|
||||
const port = process.env.PORT || 4000;
|
||||
function run(): void {
|
||||
const port = process.env['PORT'] || 4000;
|
||||
|
||||
// Start up the Node server
|
||||
const server = app();
|
||||
|
||||
@@ -1,9 +1 @@
|
||||
import { enableProdMode } from '@angular/core';
|
||||
|
||||
import { environment } from './environments/environment';
|
||||
|
||||
if (environment.production) {
|
||||
enableProdMode();
|
||||
}
|
||||
|
||||
export { AppServerModule } from './app/app.server.module';
|
||||
|
||||
@@ -2,14 +2,9 @@
|
||||
"extends": "./tsconfig.app.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "./out-tsc/app-server",
|
||||
"module": "commonjs",
|
||||
"types": ["node"]
|
||||
},
|
||||
"files": [
|
||||
"src/main.server.ts",
|
||||
"server.ts"
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"entryModule": "./src/app/app.server.module#AppServerModule"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,15 +1,10 @@
|
||||
import { Component, OnInit } from '@angular/core';
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-home',
|
||||
templateUrl: './home.component.html',
|
||||
styleUrls: ['./home.component.css']
|
||||
})
|
||||
export class HomeComponent implements OnInit {
|
||||
|
||||
constructor() { }
|
||||
|
||||
ngOnInit() {
|
||||
}
|
||||
export class HomeComponent {
|
||||
|
||||
}
|
||||
|
||||
@@ -56,8 +56,8 @@ Superpower boost: 1024
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
To examine the behavior of the `exponentialStrength` pipe in the <live-example></live-example>, change the value and optional exponent in the template.
|
||||
To examine the behavior of the `exponentialStrength` pipe in the <live-example name="pipes"></live-example>, change the value and optional exponent in the template.
|
||||
|
||||
</div>
|
||||
|
||||
@reviewed 2022-04-01
|
||||
@reviewed 2023-01-06
|
||||
|
||||
@@ -115,9 +115,6 @@ For customers to see their cart, you can create the cart view in two steps:
|
||||
|
||||
<code-example header="src/app/cart/cart.component.ts" path="getting-started/src/app/cart/cart.component.1.ts"></code-example>
|
||||
|
||||
StackBlitz also generates an `ngOnInit()` by default in components.
|
||||
You can ignore the `CartComponent` `ngOnInit()` for this tutorial.
|
||||
|
||||
1. Notice that the newly created `CartComponent` is added to the module's `declarations` in `app.module.ts`.
|
||||
|
||||
<code-example header="src/app/app.module.ts" path="getting-started/src/app/app.module.ts" region="declare-cart"></code-example>
|
||||
|
||||
@@ -41,10 +41,6 @@ You always import the `Component` symbol from the Angular core library and annot
|
||||
|
||||
The [CSS element selector](https://developer.mozilla.org/docs/Web/CSS/Type_selectors), `'app-heroes'`, matches the name of the HTML element that identifies this component within a parent component's template.
|
||||
|
||||
The `ngOnInit()` is a [lifecycle hook](guide/lifecycle-hooks#oninit).
|
||||
Angular calls `ngOnInit()` shortly after creating a component.
|
||||
It's a good place to put initialization logic.
|
||||
|
||||
Always `export` the component class so you can `import` it elsewhere … like in the `AppModule`.
|
||||
|
||||
### Add a `hero` property
|
||||
|
||||
+1
-1
@@ -131,7 +131,7 @@
|
||||
"jasmine": "~4.5.0",
|
||||
"jasmine-core": "~4.5.0",
|
||||
"jasmine-spec-reporter": "~7.0.0",
|
||||
"jsdom": "^20.0.0",
|
||||
"jsdom": "^21.0.0",
|
||||
"json-schema-traverse": "^1.0.0",
|
||||
"json5": "^2.2.0",
|
||||
"karma": "~6.4.0",
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
/**
|
||||
* @file Spec file loaded by Protractor. It is not guaranteed
|
||||
* to load before other spec files. Jasmine tests execute after all
|
||||
* files are loaded, so this file can be used for initialization.
|
||||
*/
|
||||
|
||||
// Increase the timeout for specs as Selenium & Protractor is slow.
|
||||
// Default Protractor timeout is 30 seconds.
|
||||
jasmine.DEFAULT_TIMEOUT_INTERVAL = 60000;
|
||||
@@ -57,8 +57,9 @@ export class ExampleZipper {
|
||||
return archive;
|
||||
}
|
||||
|
||||
_getExampleType(sourceFolder) {
|
||||
const filePath = path.join(sourceFolder, EXAMPLE_CONFIG_NAME);
|
||||
_getExampleType(exampleDirName) {
|
||||
const filePath = path.join(exampleDirName, EXAMPLE_CONFIG_NAME);
|
||||
|
||||
try {
|
||||
return this._loadJson(filePath).projectType || 'cli';
|
||||
} catch (err) { // empty file, so it is cli
|
||||
@@ -89,7 +90,6 @@ export class ExampleZipper {
|
||||
const jsonFileName = configFileName.replace(/^.*[\\\/]/, '');
|
||||
let relativeDirName = path.basename(sourceDirName);
|
||||
let exampleZipName;
|
||||
const exampleType = this._getExampleType(path.join(sourceDirName, relativeDirName));
|
||||
if (relativeDirName.indexOf('/') !== -1) { // Special example
|
||||
exampleZipName = relativeDirName.split('/').join('-');
|
||||
} else {
|
||||
@@ -97,6 +97,7 @@ export class ExampleZipper {
|
||||
}
|
||||
|
||||
const exampleDirName = path.dirname(configFileName);
|
||||
const exampleType = this._getExampleType(exampleDirName);
|
||||
const outputFileName = path.join(outputDirName, exampleZipName + '.zip');
|
||||
let defaultIncludes = ['**/*.ts', '**/*.js', '**/*.es6', '**/*.css', '**/*.html', '**/*.md', '**/*.json', '**/*.png', '**/*.svg'];
|
||||
let alwaysIncludes = [
|
||||
|
||||
+4
-4
@@ -8688,10 +8688,10 @@ jsdoc@^3.6.3:
|
||||
taffydb "2.6.2"
|
||||
underscore "~1.13.2"
|
||||
|
||||
jsdom@^20.0.0:
|
||||
version "20.0.3"
|
||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-20.0.3.tgz#886a41ba1d4726f67a8858028c99489fed6ad4db"
|
||||
integrity sha512-SYhBvTh89tTfCD/CRdSOm13mOBa42iTaTyfyEWBdKcGdPxPtLFBXuHR8XHb33YNYaP+lLbmSvBTsnoesCNJEsQ==
|
||||
jsdom@^21.0.0:
|
||||
version "21.0.0"
|
||||
resolved "https://registry.yarnpkg.com/jsdom/-/jsdom-21.0.0.tgz#33e22f2fc44286e50ac853c7b7656c8864a4ea45"
|
||||
integrity sha512-AIw+3ZakSUtDYvhwPwWHiZsUi3zHugpMEKlNPaurviseYoBqo0zBd3zqoUi3LPCNtPFlEP8FiW9MqCZdjb2IYA==
|
||||
dependencies:
|
||||
abab "^2.0.6"
|
||||
acorn "^8.8.1"
|
||||
|
||||
@@ -553,7 +553,7 @@ export interface FormRecord<TControl> {
|
||||
export class FormsModule {
|
||||
static withConfig(opts: {
|
||||
callSetDisabledState?: SetDisabledStateOption;
|
||||
}): ModuleWithProviders<ReactiveFormsModule>;
|
||||
}): ModuleWithProviders<FormsModule>;
|
||||
// (undocumented)
|
||||
static ɵfac: i0.ɵɵFactoryDeclaration<FormsModule, never>;
|
||||
// (undocumented)
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
* Ideally, we would run `yarn install` with the `--frozen-lockfile` option to verify that the
|
||||
* lockfile is in-sync with `package.json`, but we cannot do that for integration projects, because
|
||||
* we want to be able to install the locally built Angular packages). Therefore, we must manually
|
||||
* esnure that the integration project lockfiles remain in-sync, which is error-prone.
|
||||
* ensure that the integration project lockfiles remain in-sync, which is error-prone.
|
||||
*
|
||||
* The checks performed by this script (although not full-proof) provide another line of defense
|
||||
* against indeterminism caused by unpinned dependencies.
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "angular-srcs",
|
||||
"version": "15.1.0-next.3",
|
||||
"version": "15.1.0",
|
||||
"private": true,
|
||||
"description": "Angular - a web framework for modern web apps",
|
||||
"homepage": "https://github.com/angular/angular",
|
||||
|
||||
@@ -226,9 +226,8 @@ export function compile({
|
||||
return delegate(fileName.replace(/\.(ngfactory|ngsummary)\.ts$/, '.ts'));
|
||||
};
|
||||
|
||||
// By default, disable tsickle decorator transforming in the tsickle compiler host.
|
||||
// The Angular compilers have their own logic for decorator processing and we wouldn't
|
||||
// want tsickle to interfere with that.
|
||||
// Never run the tsickle decorator transform.
|
||||
// TODO(b/254054103): Remove the transform and this flag.
|
||||
bazelHost.transformDecorators = false;
|
||||
|
||||
// By default in the `prodmode` output, we do not add annotations for closure compiler.
|
||||
@@ -238,11 +237,6 @@ export function compile({
|
||||
if (!bazelOpts.es5Mode && !bazelOpts.devmode) {
|
||||
if (bazelOpts.workspaceName === 'google3') {
|
||||
compilerOpts.annotateForClosureCompiler = true;
|
||||
// Enable the tsickle decorator transform in google3 with Ivy mode enabled. The tsickle
|
||||
// decorator transformation is still needed. This might be because of custom decorators
|
||||
// with the `@Annotation` JSDoc that will be processed by the tsickle decorator transform.
|
||||
// TODO: Figure out why this is needed in g3 and how we can improve this. FW-2225
|
||||
bazelHost.transformDecorators = true;
|
||||
} else {
|
||||
compilerOpts.annotateForClosureCompiler = false;
|
||||
}
|
||||
|
||||
@@ -168,12 +168,9 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
|
||||
@Input()
|
||||
set ngForTrackBy(fn: TrackByFunction<T>) {
|
||||
if (NG_DEV_MODE && fn != null && typeof fn !== 'function') {
|
||||
// TODO(vicb): use a log service once there is a public one available
|
||||
if (<any>console && <any>console.warn) {
|
||||
console.warn(
|
||||
`trackBy must be a function, but received ${JSON.stringify(fn)}. ` +
|
||||
`See https://angular.io/api/common/NgForOf#change-propagation for more information.`);
|
||||
}
|
||||
console.warn(
|
||||
`trackBy must be a function, but received ${JSON.stringify(fn)}. ` +
|
||||
`See https://angular.io/api/common/NgForOf#change-propagation for more information.`);
|
||||
}
|
||||
this._trackByFn = fn;
|
||||
}
|
||||
@@ -185,7 +182,9 @@ export class NgForOf<T, U extends NgIterable<T> = NgIterable<T>> implements DoCh
|
||||
private _ngForOf: U|undefined|null = null;
|
||||
private _ngForOfDirty: boolean = true;
|
||||
private _differ: IterableDiffer<T>|null = null;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
// TODO(issue/24571): remove '!'
|
||||
// waiting for microsoft/typescript#43662 to allow the return type `TrackByFunction|undefined` for
|
||||
// the getter
|
||||
private _trackByFn!: TrackByFunction<T>;
|
||||
|
||||
constructor(
|
||||
|
||||
@@ -12,7 +12,6 @@ import {getPluralCategory, NgLocalization} from '../i18n/localization';
|
||||
|
||||
import {SwitchView} from './ng_switch';
|
||||
|
||||
|
||||
/**
|
||||
* @ngModule CommonModule
|
||||
*
|
||||
@@ -49,29 +48,25 @@ import {SwitchView} from './ng_switch';
|
||||
standalone: true,
|
||||
})
|
||||
export class NgPlural {
|
||||
// TODO(issue/24571): remove '!'.
|
||||
private _switchValue!: number;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
private _activeView!: SwitchView;
|
||||
private _activeView?: SwitchView;
|
||||
private _caseViews: {[k: string]: SwitchView} = {};
|
||||
|
||||
constructor(private _localization: NgLocalization) {}
|
||||
|
||||
@Input()
|
||||
set ngPlural(value: number) {
|
||||
this._switchValue = value;
|
||||
this._updateView();
|
||||
this._updateView(value);
|
||||
}
|
||||
|
||||
addCase(value: string, switchView: SwitchView): void {
|
||||
this._caseViews[value] = switchView;
|
||||
}
|
||||
|
||||
private _updateView(): void {
|
||||
private _updateView(switchValue: number): void {
|
||||
this._clearViews();
|
||||
|
||||
const cases = Object.keys(this._caseViews);
|
||||
const key = getPluralCategory(this._switchValue, cases, this._localization);
|
||||
const key = getPluralCategory(switchValue, cases, this._localization);
|
||||
this._activateView(this._caseViews[key]);
|
||||
}
|
||||
|
||||
|
||||
@@ -106,8 +106,7 @@ export class SwitchView {
|
||||
standalone: true,
|
||||
})
|
||||
export class NgSwitch {
|
||||
// TODO(issue/24571): remove '!'.
|
||||
private _defaultViews!: SwitchView[];
|
||||
private _defaultViews: SwitchView[] = [];
|
||||
private _defaultUsed = false;
|
||||
private _caseCount = 0;
|
||||
private _lastCaseCheckIndex = 0;
|
||||
@@ -129,9 +128,6 @@ export class NgSwitch {
|
||||
|
||||
/** @internal */
|
||||
_addDefault(view: SwitchView) {
|
||||
if (!this._defaultViews) {
|
||||
this._defaultViews = [];
|
||||
}
|
||||
this._defaultViews.push(view);
|
||||
}
|
||||
|
||||
@@ -149,10 +145,9 @@ export class NgSwitch {
|
||||
}
|
||||
|
||||
private _updateDefaultCases(useDefault: boolean) {
|
||||
if (this._defaultViews && useDefault !== this._defaultUsed) {
|
||||
if (this._defaultViews.length > 0 && useDefault !== this._defaultUsed) {
|
||||
this._defaultUsed = useDefault;
|
||||
for (let i = 0; i < this._defaultViews.length; i++) {
|
||||
const defaultView = this._defaultViews[i];
|
||||
for (const defaultView of this._defaultViews) {
|
||||
defaultView.enforceState(useDefault);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -183,7 +183,7 @@ describe('insert/remove', () => {
|
||||
fixture.componentInstance.currentComponent = Module2InjectedComponent;
|
||||
fixture.detectChanges();
|
||||
|
||||
const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef']!;
|
||||
const moduleRef = fixture.componentInstance.ngComponentOutlet?.['_moduleRef']!;
|
||||
spyOn(moduleRef, 'destroy').and.callThrough();
|
||||
|
||||
expect(moduleRef.destroy).not.toHaveBeenCalled();
|
||||
@@ -197,7 +197,7 @@ describe('insert/remove', () => {
|
||||
fixture.componentInstance.currentComponent = Module2InjectedComponent;
|
||||
fixture.detectChanges();
|
||||
|
||||
const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef']!;
|
||||
const moduleRef = fixture.componentInstance.ngComponentOutlet?.['_moduleRef']!;
|
||||
spyOn(moduleRef, 'destroy').and.callThrough();
|
||||
|
||||
expect(moduleRef.destroy).not.toHaveBeenCalled();
|
||||
@@ -213,13 +213,13 @@ describe('insert/remove', () => {
|
||||
fixture.componentInstance.currentComponent = Module2InjectedComponent;
|
||||
fixture.detectChanges();
|
||||
expect(fixture.nativeElement).toHaveText('baz');
|
||||
const moduleRef = fixture.componentInstance.ngComponentOutlet['_moduleRef'];
|
||||
const moduleRef = fixture.componentInstance.ngComponentOutlet?.['_moduleRef'];
|
||||
|
||||
fixture.componentInstance.currentComponent = Module2InjectedComponent2;
|
||||
fixture.detectChanges();
|
||||
|
||||
expect(fixture.nativeElement).toHaveText('baz2');
|
||||
expect(moduleRef).toBe(fixture.componentInstance.ngComponentOutlet['_moduleRef']);
|
||||
expect(moduleRef).toBe(fixture.componentInstance.ngComponentOutlet?.['_moduleRef']);
|
||||
}));
|
||||
|
||||
it('should re-create moduleRef when changed (NgModuleFactory)', waitForAsync(() => {
|
||||
@@ -322,16 +322,16 @@ class TestComponent {
|
||||
ngModuleFactory?: NgModuleFactory<unknown>;
|
||||
|
||||
get cmpRef(): ComponentRef<any>|undefined {
|
||||
return this.ngComponentOutlet['_componentRef'];
|
||||
return this.ngComponentOutlet?.['_componentRef'];
|
||||
}
|
||||
set cmpRef(value: ComponentRef<any>|undefined) {
|
||||
this.ngComponentOutlet['_componentRef'] = value;
|
||||
if (this.ngComponentOutlet) {
|
||||
this.ngComponentOutlet['_componentRef'] = value;
|
||||
}
|
||||
}
|
||||
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@ViewChildren(TemplateRef) tplRefs!: QueryList<TemplateRef<any>>;
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@ViewChild(NgComponentOutlet, {static: true}) ngComponentOutlet!: NgComponentOutlet;
|
||||
@ViewChildren(TemplateRef) tplRefs: QueryList<TemplateRef<any>> = new QueryList();
|
||||
@ViewChild(NgComponentOutlet, {static: true}) ngComponentOutlet?: NgComponentOutlet;
|
||||
|
||||
constructor(public vcRef: ViewContainerRef) {}
|
||||
}
|
||||
|
||||
@@ -338,14 +338,12 @@ class DestroyableCmpt implements OnDestroy {
|
||||
|
||||
@Directive({selector: 'tpl-refs', exportAs: 'tplRefs'})
|
||||
class CaptureTplRefs {
|
||||
// TODO(issue/24571): remove '!'.
|
||||
@ContentChildren(TemplateRef) tplRefs!: QueryList<TemplateRef<any>>;
|
||||
@ContentChildren(TemplateRef) tplRefs?: QueryList<TemplateRef<any>>;
|
||||
}
|
||||
|
||||
@Component({selector: 'test-cmp', template: ''})
|
||||
class TestComponent {
|
||||
// TODO(issue/24571): remove '!'.
|
||||
currentTplRef!: TemplateRef<any>;
|
||||
currentTplRef?: TemplateRef<any>;
|
||||
context: any = {foo: 'bar'};
|
||||
value = 'bar';
|
||||
injector: Injector|null = null;
|
||||
|
||||
@@ -10,7 +10,7 @@ import ts from 'typescript';
|
||||
|
||||
export function aliasTransformFactory(exportStatements: Map<string, Map<string, [string, string]>>):
|
||||
ts.TransformerFactory<ts.SourceFile> {
|
||||
return (context: ts.TransformationContext) => {
|
||||
return () => {
|
||||
return (file: ts.SourceFile) => {
|
||||
if (ts.isBundle(file) || !exportStatements.has(file.fileName)) {
|
||||
return file;
|
||||
@@ -19,10 +19,9 @@ export function aliasTransformFactory(exportStatements: Map<string, Map<string,
|
||||
const statements = [...file.statements];
|
||||
exportStatements.get(file.fileName)!.forEach(([moduleName, symbolName], aliasName) => {
|
||||
const stmt = ts.factory.createExportDeclaration(
|
||||
/* decorators */ undefined,
|
||||
/* modifiers */ undefined,
|
||||
/* isTypeOnly */ false,
|
||||
/* exportClause */ ts.createNamedExports([ts.factory.createExportSpecifier(
|
||||
/* exportClause */ ts.factory.createNamedExports([ts.factory.createExportSpecifier(
|
||||
false, symbolName, aliasName)]),
|
||||
/* moduleSpecifier */ ts.factory.createStringLiteral(moduleName));
|
||||
statements.push(stmt);
|
||||
|
||||
@@ -208,19 +208,19 @@ yarn test //packages/compiler-cli/test/compliance/linked --config=debug
|
||||
To debug generating the partial golden output use the following form of Bazel command:
|
||||
|
||||
```sh
|
||||
yarn bazel run //packages/compiler-cli/test/compliance/test_cases:generate_partial_for_<path/to/test_case>.debug
|
||||
yarn bazel run //packages/compiler-cli/test/compliance/test_cases:partial_<path/to/test_case>.debug
|
||||
```
|
||||
|
||||
The `path/to/test_case` is relative to the `test_cases` directory. So for this `TEST_CASES.json` file at:
|
||||
|
||||
```
|
||||
packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_directives/directives/matching/TEST_CASES.json
|
||||
packages/compiler-cli/test/compliance/test_cases/r3_view_compiler_directives/matching/TEST_CASES.json
|
||||
```
|
||||
|
||||
The command to debug the test-cases would be:
|
||||
|
||||
```
|
||||
yarn bazel run //packages/compiler-cli/test/compliance/test_cases:generate_partial_for_r3_view_compiler_directives/directives/matching.debug
|
||||
yarn bazel run //packages/compiler-cli/test/compliance/test_cases:partial_r3_view_compiler_directives/matching.debug
|
||||
```
|
||||
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@ export class FormsModule {
|
||||
*/
|
||||
static withConfig(opts: {
|
||||
callSetDisabledState?: SetDisabledStateOption,
|
||||
}): ModuleWithProviders<ReactiveFormsModule> {
|
||||
}): ModuleWithProviders<FormsModule> {
|
||||
return {
|
||||
ngModule: FormsModule,
|
||||
providers: [{
|
||||
|
||||
@@ -112,14 +112,14 @@ class CustomValidatorDirective implements Validator {
|
||||
|
||||
describe('composeValidators', () => {
|
||||
it('should compose functions', () => {
|
||||
const dummy1 = (_: any /** TODO #9100 */) => ({'dummy1': true});
|
||||
const dummy2 = (_: any /** TODO #9100 */) => ({'dummy2': true});
|
||||
const dummy1 = () => ({'dummy1': true});
|
||||
const dummy2 = () => ({'dummy2': true});
|
||||
const v = composeValidators([dummy1, dummy2])!;
|
||||
expect(v(new FormControl(''))).toEqual({'dummy1': true, 'dummy2': true});
|
||||
});
|
||||
|
||||
it('should compose validator directives', () => {
|
||||
const dummy1 = (_: any /** TODO #9100 */) => ({'dummy1': true});
|
||||
const dummy1 = () => ({'dummy1': true});
|
||||
const v = composeValidators([dummy1, new CustomValidatorDirective()])!;
|
||||
expect(v(new FormControl(''))).toEqual({'dummy1': true, 'custom': true});
|
||||
});
|
||||
@@ -309,10 +309,10 @@ class CustomValidatorDirective implements Validator {
|
||||
});
|
||||
|
||||
describe('NgForm', () => {
|
||||
let form: any /** TODO #9100 */;
|
||||
let form: NgForm;
|
||||
let formModel: FormGroup;
|
||||
let loginControlDir: any /** TODO #9100 */;
|
||||
let personControlGroupDir: any /** TODO #9100 */;
|
||||
let loginControlDir: NgModel;
|
||||
let personControlGroupDir: NgModelGroup;
|
||||
|
||||
beforeEach(() => {
|
||||
form = new NgForm([], []);
|
||||
@@ -384,7 +384,7 @@ class CustomValidatorDirective implements Validator {
|
||||
});
|
||||
|
||||
it('should set up sync validator', fakeAsync(() => {
|
||||
const formValidator = (c: any /** TODO #9100 */) => ({'custom': true});
|
||||
const formValidator = () => ({'custom': true});
|
||||
const f = new NgForm([formValidator], []);
|
||||
|
||||
tick();
|
||||
@@ -402,8 +402,8 @@ class CustomValidatorDirective implements Validator {
|
||||
});
|
||||
|
||||
describe('FormGroupName', () => {
|
||||
let formModel: any /** TODO #9100 */;
|
||||
let controlGroupDir: any /** TODO #9100 */;
|
||||
let formModel: FormGroup;
|
||||
let controlGroupDir: FormGroupName;
|
||||
|
||||
beforeEach(() => {
|
||||
formModel = new FormGroup({'login': new FormControl(null)});
|
||||
@@ -481,9 +481,9 @@ class CustomValidatorDirective implements Validator {
|
||||
});
|
||||
|
||||
describe('FormControlDirective', () => {
|
||||
let controlDir: any /** TODO #9100 */;
|
||||
let control: any /** TODO #9100 */;
|
||||
const checkProperties = function(control: AbstractControl) {
|
||||
let controlDir: FormControlDirective;
|
||||
let control: FormControl;
|
||||
const checkProperties = function(control: FormControl) {
|
||||
expect(controlDir.control).toBe(control);
|
||||
expect(controlDir.value).toBe(control.value);
|
||||
expect(controlDir.valid).toBe(control.valid);
|
||||
@@ -648,8 +648,8 @@ class CustomValidatorDirective implements Validator {
|
||||
});
|
||||
|
||||
describe('FormControlName', () => {
|
||||
let formModel: any /** TODO #9100 */;
|
||||
let controlNameDir: any /** TODO #9100 */;
|
||||
let formModel: FormControl;
|
||||
let controlNameDir: FormControlName;
|
||||
|
||||
beforeEach(() => {
|
||||
formModel = new FormControl('name');
|
||||
|
||||
@@ -850,7 +850,7 @@ describe('FormArray', () => {
|
||||
|
||||
describe('valueChanges', () => {
|
||||
let a: FormArray;
|
||||
let c1: any /** TODO #9100 */, c2: any /** TODO #9100 */;
|
||||
let c1: FormControl, c2: FormControl;
|
||||
|
||||
beforeEach(() => {
|
||||
c1 = new FormControl('old1');
|
||||
|
||||
@@ -11,10 +11,10 @@ import {FormBuilder, NonNullableFormBuilder, ReactiveFormsModule, UntypedFormBui
|
||||
import {of} from 'rxjs';
|
||||
|
||||
(function() {
|
||||
function syncValidator(_: any /** TODO #9100 */): any /** TODO #9100 */ {
|
||||
function syncValidator() {
|
||||
return null;
|
||||
}
|
||||
function asyncValidator(_: any /** TODO #9100 */) {
|
||||
function asyncValidator() {
|
||||
return Promise.resolve(null);
|
||||
}
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
*/
|
||||
|
||||
import {fakeAsync, tick} from '@angular/core/testing';
|
||||
import {FormArray, FormControl, FormGroup, Validators} from '@angular/forms';
|
||||
import {AsyncValidatorFn, FormArray, FormControl, FormGroup, Validators} from '@angular/forms';
|
||||
|
||||
import {asyncValidator, asyncValidatorReturningObservable} from './util';
|
||||
|
||||
@@ -16,7 +16,7 @@ function otherAsyncValidator() {
|
||||
return Promise.resolve({'other': true});
|
||||
}
|
||||
|
||||
function syncValidator(_: any /** TODO #9100 */): any /** TODO #9100 */ {
|
||||
function syncValidator() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -1105,7 +1105,7 @@ describe('FormControl', () => {
|
||||
it('should fire an event after the status has been updated to pending', fakeAsync(() => {
|
||||
const c = new FormControl('old', Validators.required, asyncValidator('expected'));
|
||||
|
||||
const log: any[] /** TODO #9100 */ = [];
|
||||
const log: string[] = [];
|
||||
c.valueChanges.subscribe({next: (value: any) => log.push(`value: '${value}'`)});
|
||||
|
||||
c.statusChanges.subscribe({next: (status: any) => log.push(`status: '${status}'`)});
|
||||
@@ -1133,7 +1133,7 @@ describe('FormControl', () => {
|
||||
|
||||
// TODO: remove the if statement after making observable delivery sync
|
||||
it('should update set errors and status before emitting an event', done => {
|
||||
c.valueChanges.subscribe((value: any /** TODO #9100 */) => {
|
||||
c.valueChanges.subscribe(() => {
|
||||
expect(c.valid).toEqual(false);
|
||||
expect(c.errors).toEqual({'required': true});
|
||||
done();
|
||||
@@ -1507,7 +1507,8 @@ describe('FormControl', () => {
|
||||
});
|
||||
|
||||
it('should throw when sync validator passed into async validator param', () => {
|
||||
const fn = () => new FormControl('', syncValidator, syncValidator);
|
||||
const fn = () =>
|
||||
new FormControl('', syncValidator, syncValidator as unknown as AsyncValidatorFn);
|
||||
// test for the specific error since without the error check it would still throw an error
|
||||
// but
|
||||
// not a meaningful one
|
||||
|
||||
@@ -30,9 +30,19 @@ esbuild(
|
||||
deps = [":factory_lib"],
|
||||
)
|
||||
|
||||
esbuild(
|
||||
name = "api_bundle",
|
||||
entry_point = ":api.ts",
|
||||
format = "cjs",
|
||||
deps = [":api"],
|
||||
)
|
||||
|
||||
extract_types(
|
||||
name = "factory_types",
|
||||
deps = [":factory_lib"],
|
||||
name = "types",
|
||||
deps = [
|
||||
":api",
|
||||
":factory_lib",
|
||||
],
|
||||
)
|
||||
|
||||
pkg_npm(
|
||||
@@ -55,8 +65,9 @@ pkg_npm(
|
||||
"//integration:__subpackages__",
|
||||
],
|
||||
deps = [
|
||||
":api_bundle",
|
||||
":factory_bundle",
|
||||
":factory_types",
|
||||
":types",
|
||||
"//packages/language-service/bundles:language-service.js",
|
||||
],
|
||||
)
|
||||
|
||||
@@ -38,6 +38,6 @@ npm_package(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
EOT
|
||||
_sedi 's#\# PLACE_HOLDER_FOR_packages/language-service/build.sh_IN_angular_REPO#data = ["//.angular_packages/language-service:package.json"], \# FOR TESTING ONLY! DO NOT COMMIT THIS LINE!#' WORKSPACE
|
||||
_sedi 's#\# PLACE_HOLDER_FOR_angular/angular_packages/language-service/build.sh#"//.angular_packages/language-service:package.json", \# FOR TESTING ONLY! DO NOT COMMIT THIS LINE!#' WORKSPACE
|
||||
yarn add @angular/language-service@file:".angular_packages/language-service"
|
||||
popd
|
||||
|
||||
@@ -9,6 +9,19 @@
|
||||
"engines": {
|
||||
"node": "^14.20.0 || ^16.13.0 || >=18.10.0"
|
||||
},
|
||||
"exports": {
|
||||
".": {
|
||||
"types": "./index.d.ts",
|
||||
"default": "./index.js"
|
||||
},
|
||||
"./package.json": {
|
||||
"default": "./package.json"
|
||||
},
|
||||
"./api": {
|
||||
"types": "./api.d.ts",
|
||||
"default": "./api_bundle.js"
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/angular/angular.git",
|
||||
|
||||
@@ -8,6 +8,7 @@ ng_module(
|
||||
name = "testing",
|
||||
srcs = glob(["**/*.ts"]),
|
||||
deps = [
|
||||
"//packages/common/testing",
|
||||
"//packages/core",
|
||||
"//packages/core/testing",
|
||||
"//packages/platform-browser",
|
||||
|
||||
@@ -5,10 +5,13 @@
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
import {PlatformLocation} from '@angular/common';
|
||||
import {MockPlatformLocation} from '@angular/common/testing';
|
||||
import {APP_ID, createPlatformFactory, NgModule, NgZone, PLATFORM_INITIALIZER, platformCore, StaticProvider} from '@angular/core';
|
||||
import {BrowserModule, ɵBrowserDomAdapter as BrowserDomAdapter} from '@angular/platform-browser';
|
||||
|
||||
import {BrowserDetection, createNgZone} from './browser_util';
|
||||
import {ENABLE_MOCK_PLATFORM_LOCATION} from './mock_platform_location_flag';
|
||||
|
||||
function initBrowserTests() {
|
||||
BrowserDomAdapter.makeCurrent();
|
||||
@@ -36,6 +39,8 @@ export const platformBrowserTesting =
|
||||
providers: [
|
||||
{provide: APP_ID, useValue: 'a'},
|
||||
{provide: NgZone, useFactory: createNgZone},
|
||||
(ENABLE_MOCK_PLATFORM_LOCATION ? [{provide: PlatformLocation, useClass: MockPlatformLocation}] :
|
||||
[]),
|
||||
]
|
||||
})
|
||||
export class BrowserTestingModule {
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
/**
|
||||
* Controls whether the `MockPlatformLocation` class should be used
|
||||
* as the `PlatformLocation` implementation when the `BrowserTestingModule`
|
||||
* is imported.
|
||||
*
|
||||
* In v16, the value of this flag will be switched to `true` to enable
|
||||
* the `MockPlatformLocation` by default.
|
||||
*/
|
||||
export const ENABLE_MOCK_PLATFORM_LOCATION = false;
|
||||
@@ -19,6 +19,7 @@ import {ActivatedRouteSnapshot, RouterStateSnapshot} from './router_state';
|
||||
* @publicApi
|
||||
*/
|
||||
export type NavigationTrigger = 'imperative'|'popstate'|'hashchange';
|
||||
export const IMPERATIVE_NAVIGATION = 'imperative';
|
||||
|
||||
/**
|
||||
* Identifies the type of a router event.
|
||||
|
||||
@@ -11,7 +11,7 @@ import {BehaviorSubject, combineLatest, EMPTY, Observable, of, Subject} from 'rx
|
||||
import {catchError, defaultIfEmpty, filter, finalize, map, switchMap, take, tap} from 'rxjs/operators';
|
||||
|
||||
import {createRouterState} from './create_router_state';
|
||||
import {Event, GuardsCheckEnd, GuardsCheckStart, NavigationCancel, NavigationCancellationCode, NavigationEnd, NavigationError, NavigationSkipped, NavigationSkippedCode, NavigationStart, NavigationTrigger, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RoutesRecognized} from './events';
|
||||
import {Event, GuardsCheckEnd, GuardsCheckStart, IMPERATIVE_NAVIGATION, NavigationCancel, NavigationCancellationCode, NavigationEnd, NavigationError, NavigationSkipped, NavigationSkippedCode, NavigationStart, NavigationTrigger, ResolveEnd, ResolveStart, RouteConfigLoadEnd, RouteConfigLoadStart, RoutesRecognized} from './events';
|
||||
import {NavigationBehaviorOptions, QueryParamsHandling, Route, Routes} from './models';
|
||||
import {isNavigationCancelingError, isRedirectingNavigationCancelingError, redirectingNavigationError} from './navigation_canceling_error';
|
||||
import {activateRoutes} from './operators/activate_routes';
|
||||
@@ -270,7 +270,6 @@ interface InternalRouterInterface {
|
||||
errorHandler: ErrorHandler;
|
||||
titleStrategy?: TitleStrategy;
|
||||
navigated: boolean;
|
||||
afterPreactivation: () => Observable<void>;
|
||||
urlHandlingStrategy: UrlHandlingStrategy;
|
||||
routeReuseStrategy: RouteReuseStrategy;
|
||||
onSameUrlNavigation: 'reload'|'ignore';
|
||||
@@ -278,7 +277,6 @@ interface InternalRouterInterface {
|
||||
urlUpdateStrategy: 'deferred'|'eager';
|
||||
serializeUrl(url: UrlTree): string;
|
||||
config: Routes;
|
||||
rootComponentType: Type<any>|null;
|
||||
setBrowserUrl(url: UrlTree, t: NavigationTransition): void;
|
||||
restoreHistory(t: NavigationTransition, restoringFromCaughtError?: boolean): void;
|
||||
scheduleNavigation(
|
||||
@@ -301,6 +299,15 @@ export class NavigationTransitions {
|
||||
return this.navigationId !== 0;
|
||||
}
|
||||
private transitions?: BehaviorSubject<NavigationTransition>;
|
||||
/**
|
||||
* Hook that enables you to pause navigation after the preactivation phase.
|
||||
* Used by `RouterModule`.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
afterPreactivation: () => Observable<void> = () => of(void 0);
|
||||
/** @internal */
|
||||
rootComponentType: Type<any>|null = null;
|
||||
|
||||
constructor() {
|
||||
const onLoadStart = (r: Route) => this.events.next(new RouteConfigLoadStart(r));
|
||||
@@ -335,7 +342,7 @@ export class NavigationTransitions {
|
||||
resolve: null,
|
||||
reject: null,
|
||||
promise: Promise.resolve(true),
|
||||
source: 'imperative',
|
||||
source: IMPERATIVE_NAVIGATION,
|
||||
restoredState: null,
|
||||
currentSnapshot: router.routerState.snapshot,
|
||||
targetSnapshot: null,
|
||||
@@ -437,7 +444,7 @@ export class NavigationTransitions {
|
||||
|
||||
// Recognize
|
||||
recognize(
|
||||
this.environmentInjector, router.rootComponentType,
|
||||
this.environmentInjector, this.rootComponentType,
|
||||
router.config, this.urlSerializer,
|
||||
router.paramsInheritanceStrategy),
|
||||
|
||||
@@ -472,7 +479,7 @@ export class NavigationTransitions {
|
||||
restoredState);
|
||||
this.events.next(navStart);
|
||||
const targetSnapshot =
|
||||
createEmptyState(extractedUrl, router.rootComponentType).snapshot;
|
||||
createEmptyState(extractedUrl, this.rootComponentType).snapshot;
|
||||
|
||||
overallTransitionState = {
|
||||
...t,
|
||||
@@ -614,7 +621,7 @@ export class NavigationTransitions {
|
||||
.pipe(defaultIfEmpty(), take(1));
|
||||
}),
|
||||
|
||||
switchTap(() => router.afterPreactivation()),
|
||||
switchTap(() => this.afterPreactivation()),
|
||||
|
||||
map((t: NavigationTransition) => {
|
||||
const targetRouterState = createRouterState(
|
||||
@@ -726,11 +733,12 @@ export class NavigationTransitions {
|
||||
isBrowserTriggeredNavigation(overallTransitionState.source)
|
||||
};
|
||||
|
||||
router.scheduleNavigation(mergedTree, 'imperative', null, extras, {
|
||||
resolve: overallTransitionState.resolve,
|
||||
reject: overallTransitionState.reject,
|
||||
promise: overallTransitionState.promise
|
||||
});
|
||||
router.scheduleNavigation(
|
||||
mergedTree, IMPERATIVE_NAVIGATION, null, extras, {
|
||||
resolve: overallTransitionState.resolve,
|
||||
reject: overallTransitionState.reject,
|
||||
promise: overallTransitionState.promise
|
||||
});
|
||||
}
|
||||
|
||||
/* All other errors should reset to the router's internal URL reference
|
||||
@@ -764,6 +772,6 @@ export class NavigationTransitions {
|
||||
}
|
||||
}
|
||||
|
||||
export function isBrowserTriggeredNavigation(source: 'imperative'|'popstate'|'hashchange') {
|
||||
return source !== 'imperative';
|
||||
export function isBrowserTriggeredNavigation(source: NavigationTrigger) {
|
||||
return source !== IMPERATIVE_NAVIGATION;
|
||||
}
|
||||
|
||||
@@ -358,7 +358,7 @@ export function withEnabledBlockingInitialNavigation(): EnabledBlockingInitialNa
|
||||
resolve(true);
|
||||
});
|
||||
|
||||
router.afterPreactivation = () => {
|
||||
injector.get(NavigationTransitions).afterPreactivation = () => {
|
||||
// Unblock APP_INITIALIZER once we get to `afterPreactivation`. At this point, we
|
||||
// assume activation will complete successfully (even though this is not
|
||||
// guaranteed).
|
||||
|
||||
@@ -12,7 +12,7 @@ import {BehaviorSubject, Observable, of, SubscriptionLike} from 'rxjs';
|
||||
|
||||
import {CreateUrlTreeStrategy} from './create_url_tree_strategy';
|
||||
import {RuntimeErrorCode} from './errors';
|
||||
import {Event, NavigationTrigger} from './events';
|
||||
import {Event, IMPERATIVE_NAVIGATION, NavigationTrigger} from './events';
|
||||
import {NavigationBehaviorOptions, OnSameUrlNavigation, Routes} from './models';
|
||||
import {Navigation, NavigationExtras, NavigationTransition, NavigationTransitions, RestoredState, UrlCreationOptions} from './navigation_transition';
|
||||
import {TitleStrategy} from './page_title_strategy';
|
||||
@@ -203,14 +203,6 @@ export class Router {
|
||||
navigated: boolean = false;
|
||||
private lastSuccessfulId: number = -1;
|
||||
|
||||
/**
|
||||
* Hook that enables you to pause navigation after the preactivation phase.
|
||||
* Used by `RouterModule`.
|
||||
*
|
||||
* @internal
|
||||
*/
|
||||
afterPreactivation: () => Observable<void> = () => of(void 0);
|
||||
|
||||
/**
|
||||
* A strategy for extracting and merging URLs.
|
||||
* Used for AngularJS to Angular migrations.
|
||||
@@ -316,9 +308,6 @@ export class Router {
|
||||
private readonly urlSerializer = inject(UrlSerializer);
|
||||
private readonly location = inject(Location);
|
||||
|
||||
/** @internal */
|
||||
rootComponentType: Type<any>|null = null;
|
||||
|
||||
constructor() {
|
||||
this.isNgZoneEnabled = inject(NgZone) instanceof NgZone && NgZone.isInAngularZone();
|
||||
|
||||
@@ -327,7 +316,7 @@ export class Router {
|
||||
this.rawUrlTree = this.currentUrlTree;
|
||||
this.browserUrlTree = this.currentUrlTree;
|
||||
|
||||
this.routerState = createEmptyState(this.currentUrlTree, this.rootComponentType);
|
||||
this.routerState = createEmptyState(this.currentUrlTree, null);
|
||||
|
||||
this.navigationTransitions.setupNavigations(this).subscribe(
|
||||
t => {
|
||||
@@ -341,10 +330,10 @@ export class Router {
|
||||
|
||||
/** @internal */
|
||||
resetRootComponentType(rootComponentType: Type<any>): void {
|
||||
this.rootComponentType = rootComponentType;
|
||||
// TODO: vsavkin router 4.0 should make the root component set to null
|
||||
// this will simplify the lifecycle of the router.
|
||||
this.routerState.root.component = this.rootComponentType;
|
||||
this.routerState.root.component = rootComponentType;
|
||||
this.navigationTransitions.rootComponentType = rootComponentType;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -353,7 +342,8 @@ export class Router {
|
||||
initialNavigation(): void {
|
||||
this.setUpLocationChangeListener();
|
||||
if (!this.navigationTransitions.hasRequestedNavigation) {
|
||||
this.navigateByUrl(this.location.path(true), {replaceUrl: true});
|
||||
const state = this.location.getState() as RestoredState;
|
||||
this.navigateToSyncWithBrowser(this.location.path(true), IMPERATIVE_NAVIGATION, state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -373,37 +363,49 @@ export class Router {
|
||||
// The `setTimeout` was added in #12160 and is likely to support Angular/AngularJS
|
||||
// hybrid apps.
|
||||
setTimeout(() => {
|
||||
const extras: NavigationExtras = {replaceUrl: true};
|
||||
|
||||
// TODO: restoredState should always include the entire state, regardless
|
||||
// of navigationId. This requires a breaking change to update the type on
|
||||
// NavigationStart’s restoredState, which currently requires navigationId
|
||||
// to always be present. The Router used to only restore history state if
|
||||
// a navigationId was present.
|
||||
|
||||
// The stored navigationId is used by the RouterScroller to retrieve the scroll
|
||||
// position for the page.
|
||||
const restoredState = event.state?.navigationId ? event.state : null;
|
||||
|
||||
// Separate to NavigationStart.restoredState, we must also restore the state to
|
||||
// history.state and generate a new navigationId, since it will be overwritten
|
||||
if (event.state) {
|
||||
const stateCopy = {...event.state} as Partial<RestoredState>;
|
||||
delete stateCopy.navigationId;
|
||||
delete stateCopy.ɵrouterPageId;
|
||||
if (Object.keys(stateCopy).length !== 0) {
|
||||
extras.state = stateCopy;
|
||||
}
|
||||
}
|
||||
|
||||
const urlTree = this.parseUrl(event['url']!);
|
||||
this.scheduleNavigation(urlTree, source, restoredState, extras);
|
||||
this.navigateToSyncWithBrowser(event['url']!, source, event.state);
|
||||
}, 0);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules a router navigation to synchronize Router state with the browser state.
|
||||
*
|
||||
* This is done as a response to a popstate event and the initial navigation. These
|
||||
* two scenarios represent times when the browser URL/state has been updated and
|
||||
* the Router needs to respond to ensure its internal state matches.
|
||||
*/
|
||||
private navigateToSyncWithBrowser(
|
||||
url: string, source: NavigationTrigger, state: RestoredState|undefined) {
|
||||
const extras: NavigationExtras = {replaceUrl: true};
|
||||
|
||||
// TODO: restoredState should always include the entire state, regardless
|
||||
// of navigationId. This requires a breaking change to update the type on
|
||||
// NavigationStart’s restoredState, which currently requires navigationId
|
||||
// to always be present. The Router used to only restore history state if
|
||||
// a navigationId was present.
|
||||
|
||||
// The stored navigationId is used by the RouterScroller to retrieve the scroll
|
||||
// position for the page.
|
||||
const restoredState = state?.navigationId ? state : null;
|
||||
|
||||
// Separate to NavigationStart.restoredState, we must also restore the state to
|
||||
// history.state and generate a new navigationId, since it will be overwritten
|
||||
if (state) {
|
||||
const stateCopy = {...state} as Partial<RestoredState>;
|
||||
delete stateCopy.navigationId;
|
||||
delete stateCopy.ɵrouterPageId;
|
||||
if (Object.keys(stateCopy).length !== 0) {
|
||||
extras.state = stateCopy;
|
||||
}
|
||||
}
|
||||
|
||||
const urlTree = this.parseUrl(url);
|
||||
this.scheduleNavigation(urlTree, source, restoredState, extras);
|
||||
}
|
||||
|
||||
/** The current URL. */
|
||||
get url(): string {
|
||||
return this.serializeUrl(this.currentUrlTree);
|
||||
@@ -561,7 +563,7 @@ export class Router {
|
||||
const urlTree = isUrlTree(url) ? url : this.parseUrl(url);
|
||||
const mergedTree = this.urlHandlingStrategy.merge(urlTree, this.rawUrlTree);
|
||||
|
||||
return this.scheduleNavigation(mergedTree, 'imperative', null, extras);
|
||||
return this.scheduleNavigation(mergedTree, IMPERATIVE_NAVIGATION, null, extras);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -686,10 +688,6 @@ export class Router {
|
||||
|
||||
let targetPageId: number;
|
||||
if (this.canceledNavigationResolution === 'computed') {
|
||||
const isInitialPage = this.currentPageId === 0;
|
||||
if (isInitialPage) {
|
||||
restoredState = this.location.getState() as RestoredState | null;
|
||||
}
|
||||
// If the `ɵrouterPageId` exist in the state then `targetpageId` should have the value of
|
||||
// `ɵrouterPageId`. This is the case for something like a page refresh where we assign the
|
||||
// target id to the previously set value for that page.
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
// This file exists to easily patch the SpyNgModuleFactoryLoader into g3
|
||||
export const EXTRA_ROUTER_TESTING_PROVIDERS = [];
|
||||
@@ -11,8 +11,6 @@ import {provideLocationMocks} from '@angular/common/testing';
|
||||
import {Compiler, inject, Injector, ModuleWithProviders, NgModule} from '@angular/core';
|
||||
import {ChildrenOutletContexts, ExtraOptions, NoPreloading, Route, Router, ROUTER_CONFIGURATION, RouteReuseStrategy, RouterModule, ROUTES, Routes, TitleStrategy, UrlHandlingStrategy, UrlSerializer, ɵflatten as flatten, ɵROUTER_PROVIDERS as ROUTER_PROVIDERS, ɵwithPreloading as withPreloading} from '@angular/router';
|
||||
|
||||
import {EXTRA_ROUTER_TESTING_PROVIDERS} from './extra_router_testing_providers';
|
||||
|
||||
function isUrlHandlingStrategy(opts: ExtraOptions|
|
||||
UrlHandlingStrategy): opts is UrlHandlingStrategy {
|
||||
// This property check is needed because UrlHandlingStrategy is an interface and doesn't exist at
|
||||
@@ -117,7 +115,6 @@ export function setupTestingRouter(
|
||||
exports: [RouterModule],
|
||||
providers: [
|
||||
ROUTER_PROVIDERS,
|
||||
EXTRA_ROUTER_TESTING_PROVIDERS,
|
||||
provideLocationMocks(),
|
||||
withPreloading(NoPreloading).ɵproviders,
|
||||
{provide: ROUTES, multi: true, useValue: []},
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
// This file exists for easily patching SpyNgModuleFactoryLoader in g3
|
||||
export default {};
|
||||
@@ -12,4 +12,3 @@
|
||||
* Entry point for all public APIs of the router/testing package.
|
||||
*/
|
||||
export * from './router_testing_module';
|
||||
export * from './spy_ng_module_factory_loader';
|
||||
|
||||
Reference in New Issue
Block a user