diff --git a/CHANGELOG.md b/CHANGELOG.md index fa74ccbf..570af8d4 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,33 @@ + +# 16.2.2 (2023-08-23) +### common +| Commit | Type | Description | +| -- | -- | -- | +| [a43c0772ea](https://github.com/angular/angular/commit/a43c0772ea74410b0492a178c656268a465d3b09) | fix | Allow safeUrl for ngSrc in NgOptimizedImage ([#51351](https://github.com/angular/angular/pull/51351)) | +### compiler-cli +| Commit | Type | Description | +| -- | -- | -- | +| [39ace8664b](https://github.com/angular/angular/commit/39ace8664b843225a75dd706236ae13e171126d3) | fix | enforce a minimum version to be used when a library uses input transform ([#51413](https://github.com/angular/angular/pull/51413)) | +### core +| Commit | Type | Description | +| -- | -- | -- | +| [36f434e49d](https://github.com/angular/angular/commit/36f434e49d24f0393950299486141a121d42e044) | fix | guard the jasmine hooks ([#51394](https://github.com/angular/angular/pull/51394)) | +### router +| Commit | Type | Description | +| -- | -- | -- | +| [b0396e7164](https://github.com/angular/angular/commit/b0396e7164c08e01d24d2d8411edf1ccf4b52826) | fix | Ensure `canceledNavigationResolution: 'computed'` works on first page ([#51441](https://github.com/angular/angular/pull/51441)) | + + + + +# 16.2.1 (2023-08-16) +### router +| Commit | Type | Description | +| -- | -- | -- | +| [232a8c1b8d](https://github.com/angular/angular/commit/232a8c1b8dadf3f886b4bd0142613d116c865759) | fix | Apply named outlets to children empty paths not appearing in the URL ([#51292](https://github.com/angular/angular/pull/51292)) | + + + # 16.2.0 (2023-08-09) ### benchpress diff --git a/aio/content/demos/first-app/src/index.html b/aio/content/demos/first-app/src/index.html index 1ac50ab8..5507514b 100644 --- a/aio/content/demos/first-app/src/index.html +++ b/aio/content/demos/first-app/src/index.html @@ -1,4 +1,5 @@ - + + Your first Angular app diff --git a/aio/content/errors/NG0507.md b/aio/content/errors/NG0507.md new file mode 100644 index 00000000..9049f09f --- /dev/null +++ b/aio/content/errors/NG0507.md @@ -0,0 +1,12 @@ +@name HTML content was altered after server-side rendering +@category runtime +@shortDescription HTML content was altered after server-side rendering + +@description +Angular throws this error when it detects that the content generated by server-side rendering (SSR) was altered after the rendering. The process of hydration relies on the content to be untouched after SSR, which also includes whitespaces and comment nodes. Those whitespaces and comment nodes must be retained in the HTML generated by the SSR process. Learn more in the [Hydration guide](guide/hydration#constraints). + +@debugging + +Typically this happens in the following cases: +* Some CDN providers have a built-in feature to remove whitespaces and comment nodes from HTML as an optimization. Please verify if there is such an option in CDN configuration and turn it off. +* If you use custom post-processing of HTML generated by SSR (as a build step), make sure that this process doesn't remove whitespaces and comment nodes. \ No newline at end of file diff --git a/aio/content/examples/animations/src/app/about.component.ts b/aio/content/examples/animations/src/app/about.component.ts index 118de933..ce81010d 100644 --- a/aio/content/examples/animations/src/app/about.component.ts +++ b/aio/content/examples/animations/src/app/about.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; @Component({ + standalone: true, selector: 'app-about', templateUrl: './about.component.html', styleUrls: ['./about.component.css'] diff --git a/aio/content/examples/animations/src/app/animations.ts b/aio/content/examples/animations/src/app/animations.ts index 0549fafc..163417d3 100644 --- a/aio/content/examples/animations/src/app/animations.ts +++ b/aio/content/examples/animations/src/app/animations.ts @@ -31,15 +31,15 @@ export const slideInAnimation = // #docregion query query(':enter', [ style({ left: '-100%' }) - ]), - query(':leave', animateChild()), + ], { optional: true }), + query(':leave', animateChild(), { optional: true }), group([ query(':leave', [ animate('300ms ease-out', style({ left: '100%' })) - ]), + ], { optional: true }), query(':enter', [ animate('300ms ease-out', style({ left: '0%' })) - ]), + ], { optional: true }), ]), ]), transition('* <=> *', [ @@ -51,19 +51,19 @@ export const slideInAnimation = left: 0, width: '100%' }) - ]), + ], { optional: true }), query(':enter', [ style({ left: '-100%' }) - ]), - query(':leave', animateChild()), + ], { optional: true }), + query(':leave', animateChild(), { optional: true }), group([ query(':leave', [ animate('200ms ease-out', style({ left: '100%', opacity: 0 })) - ]), + ], { optional: true }), query(':enter', [ animate('300ms ease-out', style({ left: '0%' })) - ]), - query('@*', animateChild()) + ], { optional: true }), + query('@*', animateChild(), { optional: true }) ]), ]) // #enddocregion query diff --git a/aio/content/examples/animations/src/app/app.component.1.ts b/aio/content/examples/animations/src/app/app.component.1.ts index 11b497be..3b2d7b14 100644 --- a/aio/content/examples/animations/src/app/app.component.1.ts +++ b/aio/content/examples/animations/src/app/app.component.1.ts @@ -2,6 +2,7 @@ import { Component, HostBinding } from '@angular/core'; @Component({ + standalone: true, selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['app.component.css'], diff --git a/aio/content/examples/animations/src/app/app.component.ts b/aio/content/examples/animations/src/app/app.component.ts index 39b2c72e..da38efa9 100644 --- a/aio/content/examples/animations/src/app/app.component.ts +++ b/aio/content/examples/animations/src/app/app.component.ts @@ -11,14 +11,16 @@ import { } from '@angular/animations'; // #enddocregion imports -import { ChildrenOutletContexts, RouterOutlet } from '@angular/router'; +import { ChildrenOutletContexts, RouterLink, RouterOutlet } from '@angular/router'; import { slideInAnimation } from './animations'; // #docregion decorator, toggle-app-animations, define @Component({ + standalone: true, selector: 'app-root', templateUrl: 'app.component.html', styleUrls: ['app.component.css'], + imports: [RouterLink, RouterOutlet], animations: [ // #enddocregion decorator slideInAnimation diff --git a/aio/content/examples/animations/src/app/app.config.ts b/aio/content/examples/animations/src/app/app.config.ts new file mode 100644 index 00000000..ebcf6bad --- /dev/null +++ b/aio/content/examples/animations/src/app/app.config.ts @@ -0,0 +1,15 @@ +import { ApplicationConfig } from '@angular/core'; +import { routes } from './app.routes'; +import { provideRouter } from '@angular/router'; +import { provideProtractorTestingSupport } from '@angular/platform-browser'; +import { provideAnimations } from '@angular/platform-browser/animations'; + + +export const appConfig: ApplicationConfig = { + providers: [ + // needed for supporting e2e tests + provideProtractorTestingSupport(), + provideRouter(routes), + provideAnimations(), + ] +}; diff --git a/aio/content/examples/animations/src/app/app.module.ts b/aio/content/examples/animations/src/app/app.routes.ts similarity index 54% rename from aio/content/examples/animations/src/app/app.module.ts rename to aio/content/examples/animations/src/app/app.routes.ts index 8be60aa8..ae0b88a7 100644 --- a/aio/content/examples/animations/src/app/app.module.ts +++ b/aio/content/examples/animations/src/app/app.routes.ts @@ -1,112 +1,73 @@ -// #docregion route-animation-data -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; -import { RouterModule } from '@angular/router'; -import { AppComponent } from './app.component'; -import { OpenCloseComponent } from './open-close.component'; +import { Routes } from '@angular/router'; import { OpenClosePageComponent } from './open-close-page.component'; -import { OpenCloseChildComponent } from './open-close.component.4'; -import { ToggleAnimationsPageComponent } from './toggle-animations-page.component'; -import { StatusSliderComponent } from './status-slider.component'; import { StatusSliderPageComponent } from './status-slider-page.component'; +import { ToggleAnimationsPageComponent } from './toggle-animations-page.component'; import { HeroListPageComponent } from './hero-list-page.component'; import { HeroListGroupPageComponent } from './hero-list-group-page.component'; -import { HeroListGroupsComponent } from './hero-list-groups.component'; import { HeroListEnterLeavePageComponent } from './hero-list-enter-leave-page.component'; -import { HeroListEnterLeaveComponent } from './hero-list-enter-leave.component'; import { HeroListAutoCalcPageComponent } from './hero-list-auto-page.component'; -import { HeroListAutoComponent } from './hero-list-auto.component'; -import { HomeComponent } from './home.component'; -import { AboutComponent } from './about.component'; import { InsertRemoveComponent } from './insert-remove.component'; import { QueryingComponent } from './querying.component'; +import { HomeComponent } from './home.component'; +import { AboutComponent } from './about.component'; - -@NgModule({ - imports: [ - BrowserModule, - BrowserAnimationsModule, - RouterModule.forRoot([ - { path: '', pathMatch: 'full', redirectTo: '/enter-leave' }, - { +// #docregion route-animation-data +export const routes: Routes = [ + { path: '', pathMatch: 'full', redirectTo: '/enter-leave' }, + { path: 'open-close', component: OpenClosePageComponent, data: { animation: 'openClosePage' } - }, - { + }, + { path: 'status', component: StatusSliderPageComponent, data: { animation: 'statusPage' } - }, - { + }, + { path: 'toggle', component: ToggleAnimationsPageComponent, data: { animation: 'togglePage' } - }, - { + }, + { path: 'heroes', component: HeroListPageComponent, data: { animation: 'filterPage' } - }, - { + }, + { path: 'hero-groups', component: HeroListGroupPageComponent, data: { animation: 'heroGroupPage' } - }, - { + }, + { path: 'enter-leave', component: HeroListEnterLeavePageComponent, data: { animation: 'enterLeavePage' } - }, - { + }, + { path: 'auto', component: HeroListAutoCalcPageComponent, data: { animation: 'autoPage' } - }, - { + }, + { path: 'insert-remove', component: InsertRemoveComponent, data: { animation: 'insertRemovePage' } - }, - { + }, + { path: 'querying', component: QueryingComponent, data: { animation: 'queryingPage' } - }, - { + }, + { path: 'home', component: HomeComponent, data: { animation: 'HomePage' } - }, - { + }, + { path: 'about', component: AboutComponent, data: { animation: 'AboutPage' } - }, - ]) - ], - // #enddocregion route-animation-data - declarations: [ - AppComponent, - StatusSliderComponent, - OpenCloseComponent, - OpenCloseChildComponent, - OpenClosePageComponent, - StatusSliderPageComponent, - ToggleAnimationsPageComponent, - HeroListPageComponent, - HeroListGroupsComponent, - HeroListGroupPageComponent, - HeroListEnterLeavePageComponent, - HeroListEnterLeaveComponent, - HeroListAutoCalcPageComponent, - HeroListAutoComponent, - HomeComponent, - InsertRemoveComponent, - QueryingComponent, - AboutComponent - ], - bootstrap: [AppComponent] -}) -export class AppModule { } + }, +]; +// #enddocregion route-animation-data diff --git a/aio/content/examples/animations/src/app/hero-list-auto-page.component.ts b/aio/content/examples/animations/src/app/hero-list-auto-page.component.ts index 78f17da6..8356f946 100644 --- a/aio/content/examples/animations/src/app/hero-list-auto-page.component.ts +++ b/aio/content/examples/animations/src/app/hero-list-auto-page.component.ts @@ -1,7 +1,9 @@ import { Component } from '@angular/core'; import { HEROES } from './mock-heroes'; +import { HeroListAutoComponent } from './hero-list-auto.component'; @Component({ + standalone: true, selector: 'app-hero-list-auto-page', template: `
@@ -9,7 +11,8 @@ import { HEROES } from './mock-heroes';
- ` + `, + imports: [HeroListAutoComponent] }) export class HeroListAutoCalcPageComponent { heroes = HEROES.slice(); diff --git a/aio/content/examples/animations/src/app/hero-list-auto.component.ts b/aio/content/examples/animations/src/app/hero-list-auto.component.ts index e77814b8..4d891b04 100644 --- a/aio/content/examples/animations/src/app/hero-list-auto.component.ts +++ b/aio/content/examples/animations/src/app/hero-list-auto.component.ts @@ -13,11 +13,14 @@ import { } from '@angular/animations'; import { Hero } from './hero'; +import { NgFor } from '@angular/common'; @Component({ + standalone: true, selector: 'app-hero-list-auto', templateUrl: 'hero-list-auto.component.html', styleUrls: ['./hero-list-page.component.css'], + imports: [NgFor], // #docregion auto-calc animations: [ trigger('shrinkOut', [ diff --git a/aio/content/examples/animations/src/app/hero-list-enter-leave-page.component.ts b/aio/content/examples/animations/src/app/hero-list-enter-leave-page.component.ts index ea816245..d615f906 100644 --- a/aio/content/examples/animations/src/app/hero-list-enter-leave-page.component.ts +++ b/aio/content/examples/animations/src/app/hero-list-enter-leave-page.component.ts @@ -1,7 +1,9 @@ import { Component } from '@angular/core'; import { HEROES } from './mock-heroes'; +import { HeroListEnterLeaveComponent } from './hero-list-enter-leave.component'; @Component({ + standalone: true, selector: 'app-hero-list-enter-leave-page', template: `
@@ -9,7 +11,8 @@ import { HEROES } from './mock-heroes';
- ` + `, + imports: [HeroListEnterLeaveComponent] }) export class HeroListEnterLeavePageComponent { heroes = HEROES.slice(); diff --git a/aio/content/examples/animations/src/app/hero-list-enter-leave.component.ts b/aio/content/examples/animations/src/app/hero-list-enter-leave.component.ts index b0b5878b..d787d584 100644 --- a/aio/content/examples/animations/src/app/hero-list-enter-leave.component.ts +++ b/aio/content/examples/animations/src/app/hero-list-enter-leave.component.ts @@ -13,8 +13,10 @@ import { } from '@angular/animations'; import { Hero } from './hero'; +import { NgFor } from '@angular/common'; @Component({ + standalone: true, selector: 'app-hero-list-enter-leave', template: ` `, styleUrls: ['./hero-list-page.component.css'], + imports: [NgFor], // #docregion animationdef animations: [ trigger('flyInOut', [ diff --git a/aio/content/examples/animations/src/app/hero-list-group-page.component.ts b/aio/content/examples/animations/src/app/hero-list-group-page.component.ts index b400126f..083f7a40 100644 --- a/aio/content/examples/animations/src/app/hero-list-group-page.component.ts +++ b/aio/content/examples/animations/src/app/hero-list-group-page.component.ts @@ -1,7 +1,9 @@ import { Component } from '@angular/core'; import { HEROES } from './mock-heroes'; +import { HeroListGroupsComponent } from './hero-list-groups.component'; @Component({ + standalone: true, selector: 'app-hero-list-groups-page', template: `
@@ -9,7 +11,8 @@ import { HEROES } from './mock-heroes';
- ` + `, + imports: [HeroListGroupsComponent] }) export class HeroListGroupPageComponent { heroes = HEROES.slice(); diff --git a/aio/content/examples/animations/src/app/hero-list-groups.component.ts b/aio/content/examples/animations/src/app/hero-list-groups.component.ts index 961a2a32..87cf915e 100644 --- a/aio/content/examples/animations/src/app/hero-list-groups.component.ts +++ b/aio/content/examples/animations/src/app/hero-list-groups.component.ts @@ -14,8 +14,10 @@ import { } from '@angular/animations'; import { Hero } from './hero'; +import { NgFor } from '@angular/common'; @Component({ + standalone: true, selector: 'app-hero-list-groups', template: ` `, styleUrls: ['./hero-list-page.component.css'], + imports: [NgFor], // #docregion animationdef animations: [ trigger('flyInOut', [ diff --git a/aio/content/examples/animations/src/app/hero-list-page.component.ts b/aio/content/examples/animations/src/app/hero-list-page.component.ts index 9829642c..cc490ec0 100644 --- a/aio/content/examples/animations/src/app/hero-list-page.component.ts +++ b/aio/content/examples/animations/src/app/hero-list-page.component.ts @@ -4,10 +4,13 @@ import { Component, HostBinding, OnInit } from '@angular/core'; import { trigger, transition, animate, style, query, stagger } from '@angular/animations'; import { HEROES } from './mock-heroes'; import { Hero } from './hero'; +import { NgFor } from '@angular/common'; // #docregion filter-animations @Component({ // #enddocregion filter-animations + standalone: true, + imports: [NgFor], selector: 'app-hero-list-page', templateUrl: 'hero-list-page.component.html', styleUrls: ['hero-list-page.component.css'], diff --git a/aio/content/examples/animations/src/app/home.component.ts b/aio/content/examples/animations/src/app/home.component.ts index 8d631e9f..81acda4c 100644 --- a/aio/content/examples/animations/src/app/home.component.ts +++ b/aio/content/examples/animations/src/app/home.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; @Component({ + standalone: true, selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.css'] diff --git a/aio/content/examples/animations/src/app/insert-remove.component.ts b/aio/content/examples/animations/src/app/insert-remove.component.ts index 012b02ad..760c8174 100644 --- a/aio/content/examples/animations/src/app/insert-remove.component.ts +++ b/aio/content/examples/animations/src/app/insert-remove.component.ts @@ -1,9 +1,12 @@ // #docplaster import { Component } from '@angular/core'; import { trigger, transition, animate, style } from '@angular/animations'; +import { NgIf } from '@angular/common'; @Component({ + standalone: true, selector: 'app-insert-remove', + imports: [NgIf], animations: [ // #docregion enter-leave-trigger trigger('myInsertRemoveTrigger', [ diff --git a/aio/content/examples/animations/src/app/open-close-page.component.ts b/aio/content/examples/animations/src/app/open-close-page.component.ts index 85ece6c3..d9b23597 100644 --- a/aio/content/examples/animations/src/app/open-close-page.component.ts +++ b/aio/content/examples/animations/src/app/open-close-page.component.ts @@ -1,6 +1,8 @@ import { Component } from '@angular/core'; +import { OpenCloseComponent } from './open-close.component'; @Component({ + standalone: true, selector: 'app-open-close-page', template: `
@@ -10,7 +12,8 @@ import { Component } from '@angular/core';
- ` + `, + imports: [OpenCloseComponent] }) export class OpenClosePageComponent { logging = false; diff --git a/aio/content/examples/animations/src/app/open-close.component.1.ts b/aio/content/examples/animations/src/app/open-close.component.1.ts index 77e33258..4285b0ff 100644 --- a/aio/content/examples/animations/src/app/open-close.component.1.ts +++ b/aio/content/examples/animations/src/app/open-close.component.1.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import { trigger, transition, state, animate, style, keyframes } from '@angular/animations'; @Component({ + standalone: true, selector: 'app-open-close', animations: [ // #docregion trigger diff --git a/aio/content/examples/animations/src/app/open-close.component.2.ts b/aio/content/examples/animations/src/app/open-close.component.2.ts index 5f13d0d8..65fbf72f 100644 --- a/aio/content/examples/animations/src/app/open-close.component.2.ts +++ b/aio/content/examples/animations/src/app/open-close.component.2.ts @@ -2,6 +2,7 @@ import { Component } from '@angular/core'; import { trigger, transition, state, animate, style } from '@angular/animations'; @Component({ + standalone: true, selector: 'app-open-close-boolean', // #docregion trigger-boolean animations: [ diff --git a/aio/content/examples/animations/src/app/open-close.component.3.ts b/aio/content/examples/animations/src/app/open-close.component.3.ts index 5bda8f9d..6dec5417 100644 --- a/aio/content/examples/animations/src/app/open-close.component.3.ts +++ b/aio/content/examples/animations/src/app/open-close.component.3.ts @@ -5,6 +5,7 @@ import { transition, trigger, useAnimation } from '@angular/animations'; import { transitionAnimation } from './animations'; @Component({ + standalone: true, selector: 'app-open-close-reusable', animations: [ trigger('openClose', [ diff --git a/aio/content/examples/animations/src/app/open-close.component.4.ts b/aio/content/examples/animations/src/app/open-close.component.4.ts index e5f591c0..854412ea 100644 --- a/aio/content/examples/animations/src/app/open-close.component.4.ts +++ b/aio/content/examples/animations/src/app/open-close.component.4.ts @@ -6,6 +6,7 @@ import { trigger, transition, state, animate, style } from '@angular/animations' // #docregion toggle-animation @Component({ // #enddocregion toggle-animation + standalone: true, selector: 'app-open-close-toggle', templateUrl: 'open-close.component.4.html', styleUrls: ['open-close.component.css'], diff --git a/aio/content/examples/animations/src/app/open-close.component.ts b/aio/content/examples/animations/src/app/open-close.component.ts index 571df8f7..5d6032f0 100644 --- a/aio/content/examples/animations/src/app/open-close.component.ts +++ b/aio/content/examples/animations/src/app/open-close.component.ts @@ -4,6 +4,7 @@ import { trigger, transition, state, animate, style, AnimationEvent } from '@ang // #docregion component, events1 @Component({ + standalone: true, selector: 'app-open-close', // #docregion trigger-wildcard1, trigger-transition animations: [ diff --git a/aio/content/examples/animations/src/app/querying.component.ts b/aio/content/examples/animations/src/app/querying.component.ts index f582a0c0..65db2ecf 100644 --- a/aio/content/examples/animations/src/app/querying.component.ts +++ b/aio/content/examples/animations/src/app/querying.component.ts @@ -13,8 +13,10 @@ import { } from '@angular/animations'; import { HEROES } from './mock-heroes'; +import { NgIf } from '@angular/common'; @Component({ + standalone: true, selector: 'app-querying', template: `