From e90f5e5f22dfd2bec6ce84e77110efd02c38cc9f Mon Sep 17 00:00:00 2001 From: Ward Bell Date: Mon, 25 Sep 2023 13:12:23 -0700 Subject: [PATCH] docs: Phase 2 Sample Code Conversions to Standalone (#51918) Phase 2 sample code conversions per instructions in doc: https://docs.google.com/document/d/1QqnVK8Mc0O1gU9ctPrs-JJ42V9_dHCuEttD_01pXh34/edit **Included** 1. ajs-quick-reference Minor changes to remove references to NgModule. Converted sample to standalone. 2. architecture Migrated the code sample. Made minor changes to remove references to NgModule. I explicitly deprecated the `architecture-module.md` page and removed it from the navigation. 4. deprecations / deprecations-guide Migrated the code sample which required pulling NgModule and Reactive Forms material into a new `deprecated` folder. Made minor changes to clarify when advice was specific to NgModule (see `loadChildren` in particular). 5. displaying-data Deleted this `displaying-data` sample entirely as there is no need for a sample app just to display a single, vanilla data binding in the deprecated `zone.md` page. Replaced reference in `zone.md` with an inline code snippet. 10. ngcontainer Converted the code sample. There is no guide page for this sample. It can be displayed in Stackblitz **Excluded** 3. cli-builder Code sample is not an app; nothing to convert. 6-9 - related to getting-started and setup. Waiting until Angular team is ready to proceed. 11. providers This is in its own commit and PR 51918 because it may not make sense to convert. See that PR for details. 12. routing-with-urlmatcher No work needed. Already Standalone. 13 schematics-for-libraries Non-trivial (see doc notes) and Angular may decide to leave as is. Should have own PR. 14 setup Non-trivial (see doc notes) and Angular may decide to leave as is. Should have own PR. PR Close #51918 --- .../src/app/app-routing.module.ts | 16 --- .../src/app/app.component.ts | 16 ++- .../ajs-quick-reference/src/app/app.config.ts | 17 +++ .../src/app/app.module.1.ts | 12 --- .../ajs-quick-reference/src/app/app.module.ts | 22 ---- .../src/app/movie-list.component.ts | 12 +++ .../src/app/movie.service.ts | 2 +- .../examples/ajs-quick-reference/src/main.ts | 9 +- .../architecture/src/app/app.component.ts | 7 +- .../architecture/src/app/app.module.ts | 34 ------ .../architecture/src/app/backend.service.ts | 2 +- .../src/app/hero-detail.component.ts | 5 +- .../src/app/hero-list.component.ts | 4 + .../architecture/src/app/hero.service.ts | 4 +- .../architecture/src/app/logger.service.ts | 2 +- .../examples/architecture/src/app/mini-app.ts | 7 +- .../src/app/sales-tax.component.ts | 5 +- .../architecture/src/app/sales-tax.service.ts | 2 +- .../architecture/src/app/tax-rate.service.ts | 2 +- aio/content/examples/architecture/src/main.ts | 12 ++- .../src/app/app.component.1.html | 6 -- .../src/app/app.component.css | 0 .../src/app/app.component.html | 12 --- .../src/app/app.component.spec.ts | 20 ---- .../src/app/app.component.ts | 15 ++- .../deprecation-guide/src/app/app.config.ts | 12 +++ .../deprecation-guide/src/app/app.routes.ts | 8 ++ .../src/app/lazy/lazy.component.css | 0 .../src/app/lazy/lazy.component.html | 1 - .../src/app/lazy/lazy.component.spec.ts | 25 ----- .../src/app/lazy/lazy.component.ts | 4 +- .../src/app/lazy/lazy.routes.ts | 7 ++ .../submit-button.component.ts | 13 ++- .../submit-button/submit-button.component.css | 0 .../submit-button.component.html | 1 - .../submit-button.component.spec.ts | 25 ----- .../src/deprecated/app.component.html | 17 +++ .../src/deprecated/app.component.ts | 39 +++++++ .../src/{app => deprecated}/app.module.ts | 21 +++- .../lazy/lazy-routing.module.ts | 0 .../src/deprecated/lazy/lazy.component.ts | 7 ++ .../{app => deprecated}/lazy/lazy.module.ts | 1 - .../src/deprecated/readme.md | 2 + .../examples/deprecation-guide/src/main.ts | 8 +- .../examples/displaying-data/BUILD.bazel | 7 -- .../displaying-data/e2e/src/app.e2e-spec.ts | 25 ----- .../displaying-data/example-config.json | 0 .../src/app/app-ctor.component.1.ts | 13 --- .../src/app/app.component.1.ts | 13 --- .../src/app/app.component.2.ts | 20 ---- .../src/app/app.component.3.ts | 27 ----- .../displaying-data/src/app/app.component.ts | 28 ----- .../displaying-data/src/app/app.module.ts | 16 --- .../examples/displaying-data/src/app/hero.ts | 5 - .../examples/displaying-data/src/index.html | 13 --- .../examples/displaying-data/src/main.ts | 7 -- .../examples/displaying-data/stackblitz.json | 11 -- aio/content/examples/examples.bzl | 1 - .../ngcontainer/src/app/app.component.html | 2 - .../ngcontainer/src/app/app.component.ts | 7 +- .../ngcontainer/src/app/app.module.ts | 19 ---- .../ngcontainer/src/app/content.component.ts | 1 + .../ngcontainer/src/app/hero.components.ts | 5 +- aio/content/examples/ngcontainer/src/main.ts | 12 ++- aio/content/guide/ajs-quick-reference.md | 27 ++--- aio/content/guide/architecture-components.md | 8 +- aio/content/guide/architecture-modules.md | 17 ++- aio/content/guide/architecture-next-steps.md | 3 +- aio/content/guide/architecture-services.md | 49 +++------ aio/content/guide/architecture.md | 69 +++--------- aio/content/guide/deprecations.md | 102 +++++++++++------- aio/content/guide/glossary.md | 2 +- aio/content/guide/lazy-loading-ngmodules.md | 11 ++ aio/content/guide/zone.md | 10 +- aio/content/navigation.json | 15 +-- 75 files changed, 378 insertions(+), 603 deletions(-) delete mode 100644 aio/content/examples/ajs-quick-reference/src/app/app-routing.module.ts create mode 100644 aio/content/examples/ajs-quick-reference/src/app/app.config.ts delete mode 100644 aio/content/examples/ajs-quick-reference/src/app/app.module.1.ts delete mode 100644 aio/content/examples/ajs-quick-reference/src/app/app.module.ts delete mode 100644 aio/content/examples/architecture/src/app/app.module.ts delete mode 100644 aio/content/examples/deprecation-guide/src/app/app.component.1.html delete mode 100644 aio/content/examples/deprecation-guide/src/app/app.component.css delete mode 100644 aio/content/examples/deprecation-guide/src/app/app.component.spec.ts create mode 100644 aio/content/examples/deprecation-guide/src/app/app.config.ts create mode 100644 aio/content/examples/deprecation-guide/src/app/app.routes.ts delete mode 100644 aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.css delete mode 100644 aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.html delete mode 100644 aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.spec.ts create mode 100644 aio/content/examples/deprecation-guide/src/app/lazy/lazy.routes.ts rename aio/content/examples/deprecation-guide/src/app/{submit-button => }/submit-button.component.ts (80%) delete mode 100644 aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.css delete mode 100644 aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.html delete mode 100644 aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.spec.ts create mode 100644 aio/content/examples/deprecation-guide/src/deprecated/app.component.html create mode 100644 aio/content/examples/deprecation-guide/src/deprecated/app.component.ts rename aio/content/examples/deprecation-guide/src/{app => deprecated}/app.module.ts (68%) rename aio/content/examples/deprecation-guide/src/{app => deprecated}/lazy/lazy-routing.module.ts (100%) create mode 100644 aio/content/examples/deprecation-guide/src/deprecated/lazy/lazy.component.ts rename aio/content/examples/deprecation-guide/src/{app => deprecated}/lazy/lazy.module.ts (99%) create mode 100644 aio/content/examples/deprecation-guide/src/deprecated/readme.md delete mode 100644 aio/content/examples/displaying-data/BUILD.bazel delete mode 100644 aio/content/examples/displaying-data/e2e/src/app.e2e-spec.ts delete mode 100644 aio/content/examples/displaying-data/example-config.json delete mode 100644 aio/content/examples/displaying-data/src/app/app-ctor.component.1.ts delete mode 100644 aio/content/examples/displaying-data/src/app/app.component.1.ts delete mode 100644 aio/content/examples/displaying-data/src/app/app.component.2.ts delete mode 100644 aio/content/examples/displaying-data/src/app/app.component.3.ts delete mode 100644 aio/content/examples/displaying-data/src/app/app.component.ts delete mode 100644 aio/content/examples/displaying-data/src/app/app.module.ts delete mode 100644 aio/content/examples/displaying-data/src/app/hero.ts delete mode 100644 aio/content/examples/displaying-data/src/index.html delete mode 100644 aio/content/examples/displaying-data/src/main.ts delete mode 100644 aio/content/examples/displaying-data/stackblitz.json delete mode 100644 aio/content/examples/ngcontainer/src/app/app.module.ts diff --git a/aio/content/examples/ajs-quick-reference/src/app/app-routing.module.ts b/aio/content/examples/ajs-quick-reference/src/app/app-routing.module.ts deleted file mode 100644 index e00e4e4c629..00000000000 --- a/aio/content/examples/ajs-quick-reference/src/app/app-routing.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -// #docregion -import { NgModule } from '@angular/core'; -import { Routes, RouterModule } from '@angular/router'; - -import { MovieListComponent } from './movie-list.component'; - -const routes: Routes = [ - { path: '', redirectTo: '/movies', pathMatch: 'full' }, - { path: 'movies', component: MovieListComponent } -]; - -@NgModule({ - imports: [RouterModule.forRoot(routes)], - exports: [RouterModule] -}) -export class AppRoutingModule {} diff --git a/aio/content/examples/ajs-quick-reference/src/app/app.component.ts b/aio/content/examples/ajs-quick-reference/src/app/app.component.ts index 8a8fe49e8f5..7af2cfee1ba 100644 --- a/aio/content/examples/ajs-quick-reference/src/app/app.component.ts +++ b/aio/content/examples/ajs-quick-reference/src/app/app.component.ts @@ -1,13 +1,25 @@ import { Component } from '@angular/core'; +import { + NgFor, NgIf, NgClass, NgStyle, + CurrencyPipe, DatePipe, DecimalPipe, JsonPipe, LowerCasePipe, PercentPipe, SlicePipe, UpperCasePipe +} from '@angular/common'; +import { FormsModule } from '@angular/forms'; +import { RouterLink, RouterOutlet} from '@angular/router'; import { MovieService } from './movie.service'; import { IMovie } from './movie'; @Component({ + standalone: true, selector: 'app-root', templateUrl: './app.component.html', - styleUrls: [ './app.component.css' ], - providers: [ MovieService ] + imports: [ + FormsModule, + NgFor, NgIf, NgClass, NgStyle, + CurrencyPipe, DatePipe, DecimalPipe, JsonPipe, LowerCasePipe, PercentPipe, SlicePipe, UpperCasePipe, + RouterLink, RouterOutlet + ], + styleUrls: [ './app.component.css' ] }) export class AppComponent { diff --git a/aio/content/examples/ajs-quick-reference/src/app/app.config.ts b/aio/content/examples/ajs-quick-reference/src/app/app.config.ts new file mode 100644 index 00000000000..864f25f8bda --- /dev/null +++ b/aio/content/examples/ajs-quick-reference/src/app/app.config.ts @@ -0,0 +1,17 @@ +import { ApplicationConfig } from '@angular/core'; +import { provideRouter, Routes } from '@angular/router'; +import { provideProtractorTestingSupport } from '@angular/platform-browser'; + +import { MovieListComponent } from './movie-list.component'; + +const routes: Routes = [ + { path: '', redirectTo: '/movies', pathMatch: 'full' }, + { path: 'movies', component: MovieListComponent } +]; + +export const appConfig: ApplicationConfig = { + providers: [ + provideRouter(routes), + provideProtractorTestingSupport(), // essential for e2e testing + ], +}; diff --git a/aio/content/examples/ajs-quick-reference/src/app/app.module.1.ts b/aio/content/examples/ajs-quick-reference/src/app/app.module.1.ts deleted file mode 100644 index 530cd295e79..00000000000 --- a/aio/content/examples/ajs-quick-reference/src/app/app.module.1.ts +++ /dev/null @@ -1,12 +0,0 @@ -// #docregion -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { AppComponent } from './app.component'; - -@NgModule({ - imports: [ BrowserModule ], - declarations: [ AppComponent ], - bootstrap: [ AppComponent ] -}) -export class AppModule { } diff --git a/aio/content/examples/ajs-quick-reference/src/app/app.module.ts b/aio/content/examples/ajs-quick-reference/src/app/app.module.ts deleted file mode 100644 index 46ae679ee00..00000000000 --- a/aio/content/examples/ajs-quick-reference/src/app/app.module.ts +++ /dev/null @@ -1,22 +0,0 @@ -// #docregion -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; -import { FormsModule } from '@angular/forms'; - -import { AppComponent } from './app.component'; -import { MovieListComponent } from './movie-list.component'; -import { AppRoutingModule } from './app-routing.module'; - -@NgModule({ - imports: [ - BrowserModule, - FormsModule, - AppRoutingModule - ], - declarations: [ - AppComponent, - MovieListComponent - ], - bootstrap: [ AppComponent ] -}) -export class AppModule { } diff --git a/aio/content/examples/ajs-quick-reference/src/app/movie-list.component.ts b/aio/content/examples/ajs-quick-reference/src/app/movie-list.component.ts index e50b1d4cda3..2e6a97f43d3 100644 --- a/aio/content/examples/ajs-quick-reference/src/app/movie-list.component.ts +++ b/aio/content/examples/ajs-quick-reference/src/app/movie-list.component.ts @@ -1,12 +1,24 @@ // #docplaster import { Component } from '@angular/core'; +import { + NgFor, NgIf, NgSwitch, NgSwitchCase, NgSwitchDefault, + CurrencyPipe, DatePipe, DecimalPipe, PercentPipe, UpperCasePipe +} from '@angular/common'; +import { FormsModule } from '@angular/forms'; + import { IMovie } from './movie'; import { MovieService } from './movie.service'; // #docregion component @Component({ + standalone: true, selector: 'app-movie-list', templateUrl: './movie-list.component.html', + imports: [ + FormsModule, + NgFor, NgIf, NgSwitch, NgSwitchCase, NgSwitchDefault, + CurrencyPipe, DatePipe, DecimalPipe, PercentPipe, UpperCasePipe + ], // #docregion style-url styleUrls: [ './movie-list.component.css' ], // #enddocregion style-url diff --git a/aio/content/examples/ajs-quick-reference/src/app/movie.service.ts b/aio/content/examples/ajs-quick-reference/src/app/movie.service.ts index cbe8299b2ec..ca30896d150 100644 --- a/aio/content/examples/ajs-quick-reference/src/app/movie.service.ts +++ b/aio/content/examples/ajs-quick-reference/src/app/movie.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { IMovie } from './movie'; -@Injectable() +@Injectable({providedIn: 'root'}) export class MovieService { getMovies(): IMovie[] { return [ diff --git a/aio/content/examples/ajs-quick-reference/src/main.ts b/aio/content/examples/ajs-quick-reference/src/main.ts index 49432aa0877..b22b12f3184 100644 --- a/aio/content/examples/ajs-quick-reference/src/main.ts +++ b/aio/content/examples/ajs-quick-reference/src/main.ts @@ -1,7 +1,6 @@ -// #docregion -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { bootstrapApplication } from '@angular/platform-browser'; -import { AppModule } from './app/app.module'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); +bootstrapApplication(AppComponent, appConfig); diff --git a/aio/content/examples/architecture/src/app/app.component.ts b/aio/content/examples/architecture/src/app/app.component.ts index c3b3518c2b9..d7e30cc7594 100644 --- a/aio/content/examples/architecture/src/app/app.component.ts +++ b/aio/content/examples/architecture/src/app/app.component.ts @@ -2,12 +2,17 @@ import { Component } from '@angular/core'; // #enddocregion import +import { HeroListComponent } from './hero-list.component'; +import { SalesTaxComponent } from './sales-tax.component'; + @Component({ + standalone: true, selector: 'app-root', template: `

Architecture Example

- ` + `, + imports: [HeroListComponent, SalesTaxComponent] }) export class AppComponent { } diff --git a/aio/content/examples/architecture/src/app/app.module.ts b/aio/content/examples/architecture/src/app/app.module.ts deleted file mode 100644 index 2090120042d..00000000000 --- a/aio/content/examples/architecture/src/app/app.module.ts +++ /dev/null @@ -1,34 +0,0 @@ -import { BrowserModule } from '@angular/platform-browser'; -import { FormsModule } from '@angular/forms'; -// #docregion imports -import { NgModule } from '@angular/core'; -import { AppComponent } from './app.component'; -// #enddocregion imports -import { HeroDetailComponent } from './hero-detail.component'; -import { HeroListComponent } from './hero-list.component'; -import { SalesTaxComponent } from './sales-tax.component'; -import { HeroService } from './hero.service'; -import { BackendService } from './backend.service'; -import { Logger } from './logger.service'; - -@NgModule({ - imports: [ - BrowserModule, - FormsModule - ], - declarations: [ - AppComponent, - HeroDetailComponent, - HeroListComponent, - SalesTaxComponent - ], - providers: [ - BackendService, - HeroService, - Logger - ], - bootstrap: [ AppComponent ] -}) -// #docregion export -export class AppModule { } -// #enddocregion export diff --git a/aio/content/examples/architecture/src/app/backend.service.ts b/aio/content/examples/architecture/src/app/backend.service.ts index 3385f9e4fc7..9e2a7e19877 100644 --- a/aio/content/examples/architecture/src/app/backend.service.ts +++ b/aio/content/examples/architecture/src/app/backend.service.ts @@ -9,7 +9,7 @@ const HEROES = [ new Hero('Magneta', 'Manipulates metallic objects') ]; -@Injectable() +@Injectable({providedIn: 'root'}) export class BackendService { constructor(private logger: Logger) {} diff --git a/aio/content/examples/architecture/src/app/hero-detail.component.ts b/aio/content/examples/architecture/src/app/hero-detail.component.ts index 2a5484a08ed..f70ff7179a6 100644 --- a/aio/content/examples/architecture/src/app/hero-detail.component.ts +++ b/aio/content/examples/architecture/src/app/hero-detail.component.ts @@ -1,10 +1,13 @@ import { Component, Input } from '@angular/core'; +import { FormsModule } from '@angular/forms'; import { Hero } from './hero'; @Component({ + standalone: true, selector: 'app-hero-detail', - templateUrl: './hero-detail.component.html' + templateUrl: './hero-detail.component.html', + imports: [FormsModule] }) export class HeroDetailComponent { @Input() hero!: Hero; diff --git a/aio/content/examples/architecture/src/app/hero-list.component.ts b/aio/content/examples/architecture/src/app/hero-list.component.ts index 6f779a483bd..766237f0a77 100644 --- a/aio/content/examples/architecture/src/app/hero-list.component.ts +++ b/aio/content/examples/architecture/src/app/hero-list.component.ts @@ -1,12 +1,16 @@ import { Component, OnInit } from '@angular/core'; +import { NgFor, NgIf } from '@angular/common'; import { Hero } from './hero'; +import { HeroDetailComponent } from './hero-detail.component'; import { HeroService } from './hero.service'; // #docregion metadata, providers @Component({ + standalone: true, selector: 'app-hero-list', templateUrl: './hero-list.component.html', + imports: [ NgFor, NgIf, HeroDetailComponent ], providers: [ HeroService ] }) // #enddocregion providers diff --git a/aio/content/examples/architecture/src/app/hero.service.ts b/aio/content/examples/architecture/src/app/hero.service.ts index 493f064e408..0959cf07f89 100644 --- a/aio/content/examples/architecture/src/app/hero.service.ts +++ b/aio/content/examples/architecture/src/app/hero.service.ts @@ -4,9 +4,11 @@ import { Hero } from './hero'; import { BackendService } from './backend.service'; import { Logger } from './logger.service'; -@Injectable() +// #docregion provide +@Injectable({providedIn: 'root'}) // #docregion class export class HeroService { +// #enddocregion provide private heroes: Hero[] = []; constructor( diff --git a/aio/content/examples/architecture/src/app/logger.service.ts b/aio/content/examples/architecture/src/app/logger.service.ts index 9277ee8bc0a..a20ca2e22d5 100644 --- a/aio/content/examples/architecture/src/app/logger.service.ts +++ b/aio/content/examples/architecture/src/app/logger.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; -@Injectable() +@Injectable({providedIn: 'root'}) // #docregion class export class Logger { log(msg: any) { console.log(msg); } diff --git a/aio/content/examples/architecture/src/app/mini-app.ts b/aio/content/examples/architecture/src/app/mini-app.ts index 42d19c59dda..254e3a73701 100644 --- a/aio/content/examples/architecture/src/app/mini-app.ts +++ b/aio/content/examples/architecture/src/app/mini-app.ts @@ -19,11 +19,11 @@ export class AppComponent { } } -// #docregion module +// #docregion imports, module import { NgModule } from '@angular/core'; // #docregion import-browser-module import { BrowserModule } from '@angular/platform-browser'; -// #enddocregion import-browser-module +// #enddocregion imports, import-browser-module @NgModule({ // #docregion ngmodule-imports imports: [ BrowserModule ], @@ -33,8 +33,9 @@ import { BrowserModule } from '@angular/platform-browser'; exports: [ AppComponent ], bootstrap: [ AppComponent ] }) +// #docregion export export class AppModule { } -// #enddocregion module +// #enddocregion export,module import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; diff --git a/aio/content/examples/architecture/src/app/sales-tax.component.ts b/aio/content/examples/architecture/src/app/sales-tax.component.ts index f47fcb5daf2..3804c94eabf 100644 --- a/aio/content/examples/architecture/src/app/sales-tax.component.ts +++ b/aio/content/examples/architecture/src/app/sales-tax.component.ts @@ -1,9 +1,10 @@ import { Component } from '@angular/core'; +import { NgIf, CurrencyPipe } from '@angular/common'; import { SalesTaxService } from './sales-tax.service'; -import { TaxRateService } from './tax-rate.service'; @Component({ + standalone: true, selector: 'app-sales-tax', template: `

Sales Tax Calculator

@@ -15,7 +16,7 @@ import { TaxRateService } from './tax-rate.service'; {{ getTax(amountBox.value) | currency:'USD':true:'1.2-2' }}

`, - providers: [SalesTaxService, TaxRateService] + imports: [NgIf, CurrencyPipe] }) export class SalesTaxComponent { constructor(private salesTaxService: SalesTaxService) { } diff --git a/aio/content/examples/architecture/src/app/sales-tax.service.ts b/aio/content/examples/architecture/src/app/sales-tax.service.ts index 8e92096dd67..6ad99eccc87 100644 --- a/aio/content/examples/architecture/src/app/sales-tax.service.ts +++ b/aio/content/examples/architecture/src/app/sales-tax.service.ts @@ -2,7 +2,7 @@ import { Injectable } from '@angular/core'; import { TaxRateService } from './tax-rate.service'; -@Injectable() +@Injectable({providedIn: 'root'}) export class SalesTaxService { constructor(private rateService: TaxRateService) { } diff --git a/aio/content/examples/architecture/src/app/tax-rate.service.ts b/aio/content/examples/architecture/src/app/tax-rate.service.ts index fff2f4df8f3..6413337b76a 100644 --- a/aio/content/examples/architecture/src/app/tax-rate.service.ts +++ b/aio/content/examples/architecture/src/app/tax-rate.service.ts @@ -1,6 +1,6 @@ import { Injectable } from '@angular/core'; -@Injectable() +@Injectable({providedIn: 'root'}) export class TaxRateService { getRate(rateName: string) { return 0.10; } // 10% everywhere } diff --git a/aio/content/examples/architecture/src/main.ts b/aio/content/examples/architecture/src/main.ts index 49432aa0877..5a2dcb1b362 100644 --- a/aio/content/examples/architecture/src/main.ts +++ b/aio/content/examples/architecture/src/main.ts @@ -1,7 +1,9 @@ -// #docregion -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { bootstrapApplication, provideProtractorTestingSupport } from '@angular/platform-browser'; -import { AppModule } from './app/app.module'; +import {AppComponent} from './app/app.component'; -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); +bootstrapApplication(AppComponent, { + providers: [ + provideProtractorTestingSupport(), // essential for e2e testing + ] +}); diff --git a/aio/content/examples/deprecation-guide/src/app/app.component.1.html b/aio/content/examples/deprecation-guide/src/app/app.component.1.html deleted file mode 100644 index 2c867f873ef..00000000000 --- a/aio/content/examples/deprecation-guide/src/app/app.component.1.html +++ /dev/null @@ -1,6 +0,0 @@ - - \ No newline at end of file diff --git a/aio/content/examples/deprecation-guide/src/app/app.component.css b/aio/content/examples/deprecation-guide/src/app/app.component.css deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/aio/content/examples/deprecation-guide/src/app/app.component.html b/aio/content/examples/deprecation-guide/src/app/app.component.html index 130bffb626d..ea3ac7a8e92 100644 --- a/aio/content/examples/deprecation-guide/src/app/app.component.html +++ b/aio/content/examples/deprecation-guide/src/app/app.component.html @@ -1,17 +1,5 @@

Deprecation

- - - - - - - - - - - - diff --git a/aio/content/examples/deprecation-guide/src/app/app.component.spec.ts b/aio/content/examples/deprecation-guide/src/app/app.component.spec.ts deleted file mode 100644 index 0509746ff04..00000000000 --- a/aio/content/examples/deprecation-guide/src/app/app.component.spec.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { TestBed } from '@angular/core/testing'; -import { AppComponent } from './app.component'; - -describe('AppComponent', () => { - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ - AppComponent - ], - }).compileComponents(); - }); - - it('should create the app', () => { - const fixture = TestBed.createComponent(AppComponent); - const app = fixture.componentInstance; - expect(app).toBeTruthy(); - }); - - // Add your unit tests here -}); diff --git a/aio/content/examples/deprecation-guide/src/app/app.component.ts b/aio/content/examples/deprecation-guide/src/app/app.component.ts index 8c1baa56573..15d8f7218e6 100644 --- a/aio/content/examples/deprecation-guide/src/app/app.component.ts +++ b/aio/content/examples/deprecation-guide/src/app/app.component.ts @@ -1,12 +1,15 @@ // #docplaster import { Component, ContentChild, Input, OnInit, TemplateRef } from '@angular/core'; +import { NgFor } from '@angular/common'; import { + FormsModule, FormControl, } from '@angular/forms'; @Component({ + standalone: true, selector: 'app-root', templateUrl: './app.component.html', - styleUrls: ['./app.component.css'] + imports: [ FormsModule, NgFor ] }) export class AppComponent implements OnInit { title = 'example'; @@ -16,23 +19,17 @@ export class AppComponent implements OnInit { 'repeat-value' ]; - /* - // #docregion template-with-input-deprecated - @Input() @ContentChild(TemplateRef) tpldeprecated !: TemplateRef; - // #enddocregion template-with-input-deprecated - */ - // #docregion template-with-input @Input() tpl !: TemplateRef; @ContentChild(TemplateRef) inlineTemplate !: TemplateRef; // #enddocregion template-with-input ngOnInit() { - // #docregion deprecated-example, template-driven-form-example + // #docregion template-driven-form-example this.value = 'some value'; - // #enddocregion deprecated-example, template-driven-form-example + // #enddocregion template-driven-form-example this.setValue(); } diff --git a/aio/content/examples/deprecation-guide/src/app/app.config.ts b/aio/content/examples/deprecation-guide/src/app/app.config.ts new file mode 100644 index 00000000000..baf55bcb2f8 --- /dev/null +++ b/aio/content/examples/deprecation-guide/src/app/app.config.ts @@ -0,0 +1,12 @@ +import { ApplicationConfig } from '@angular/core'; +import { provideRouter } from '@angular/router'; +import { provideProtractorTestingSupport } from '@angular/platform-browser'; + +import { routes } from './app.routes'; + +export const appConfig: ApplicationConfig = { + providers: [ + provideRouter(routes), + provideProtractorTestingSupport(), // essential for e2e testing + ], +}; diff --git a/aio/content/examples/deprecation-guide/src/app/app.routes.ts b/aio/content/examples/deprecation-guide/src/app/app.routes.ts new file mode 100644 index 00000000000..53cf98e87c9 --- /dev/null +++ b/aio/content/examples/deprecation-guide/src/app/app.routes.ts @@ -0,0 +1,8 @@ +import { Routes } from '@angular/router'; + +export const routes: Routes = [{ + path: 'lazy', + loadComponent: () => import('./lazy/lazy.component').then(m => m.LazyComponent) + // If you want to use loadChildren for a child route tree, you can do this: + // loadChildren: () => import('./lazy/lazy.routes') +}]; diff --git a/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.css b/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.css deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.html b/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.html deleted file mode 100644 index a91819a73cb..00000000000 --- a/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.html +++ /dev/null @@ -1 +0,0 @@ -

lazy works!

diff --git a/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.spec.ts b/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.spec.ts deleted file mode 100644 index 8358b35a50f..00000000000 --- a/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { LazyComponent } from './lazy.component'; - -describe('LazyComponent', () => { - let component: LazyComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ LazyComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(LazyComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.ts b/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.ts index 79a5cd87a8e..1665ed58fb2 100644 --- a/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.ts +++ b/aio/content/examples/deprecation-guide/src/app/lazy/lazy.component.ts @@ -1,8 +1,8 @@ import { Component } from '@angular/core'; @Component({ + standalone: true, selector: 'app-lazy', - templateUrl: './lazy.component.html', - styleUrls: ['./lazy.component.css'] + template: `

lazy works!

` }) export class LazyComponent {} diff --git a/aio/content/examples/deprecation-guide/src/app/lazy/lazy.routes.ts b/aio/content/examples/deprecation-guide/src/app/lazy/lazy.routes.ts new file mode 100644 index 00000000000..ef17f3b8b72 --- /dev/null +++ b/aio/content/examples/deprecation-guide/src/app/lazy/lazy.routes.ts @@ -0,0 +1,7 @@ +import { Route } from '@angular/router'; +import { LazyComponent } from './lazy.component'; + +export default [ + { path: '*', component: LazyComponent }, + // ... more child routes ... +] as Route[]; diff --git a/aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.ts b/aio/content/examples/deprecation-guide/src/app/submit-button.component.ts similarity index 80% rename from aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.ts rename to aio/content/examples/deprecation-guide/src/app/submit-button.component.ts index 5ecac3a358f..38c94d89826 100644 --- a/aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.ts +++ b/aio/content/examples/deprecation-guide/src/app/submit-button.component.ts @@ -1,12 +1,11 @@ -// #docplaster ... +// #docplaster import { Component, Input } from '@angular/core'; // #docregion submitButton, submitButtonNarrow @Component({ - // #enddocregion submitButton, submitButtonNarrow -// #docplaster +// #enddocregion submitButton, submitButtonNarrow + standalone: true, selector: 'app-submit-button', - templateUrl: './submit-button.component.html', - styleUrls: ['./submit-button.component.css'] + template: `

submit-button works!

` // #docregion submitButton, submitButtonNarrow }) export class SubmitButtonComponent { @@ -24,9 +23,9 @@ export class SubmitButtonComponent { } // #enddocregion submitButton @Component({ + standalone: true, selector: 'app-submit-button-valid', - templateUrl: './submit-button.component.html', - styleUrls: ['./submit-button.component.css'] + template: `

submit-button works!

` }) export class SubmitButtonValidComponent { diff --git a/aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.css b/aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.css deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.html b/aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.html deleted file mode 100644 index 1cfaec5709d..00000000000 --- a/aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.html +++ /dev/null @@ -1 +0,0 @@ -

submit-button works!

diff --git a/aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.spec.ts b/aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.spec.ts deleted file mode 100644 index 9bca1aa68f1..00000000000 --- a/aio/content/examples/deprecation-guide/src/app/submit-button/submit-button.component.spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { ComponentFixture, TestBed } from '@angular/core/testing'; - -import { SubmitButtonComponent } from './submit-button.component'; - -describe('SubmitButtonComponent', () => { - let component: SubmitButtonComponent; - let fixture: ComponentFixture; - - beforeEach(async () => { - await TestBed.configureTestingModule({ - declarations: [ SubmitButtonComponent ] - }) - .compileComponents(); - }); - - beforeEach(() => { - fixture = TestBed.createComponent(SubmitButtonComponent); - component = fixture.componentInstance; - fixture.detectChanges(); - }); - - it('should create', () => { - expect(component).toBeTruthy(); - }); -}); diff --git a/aio/content/examples/deprecation-guide/src/deprecated/app.component.html b/aio/content/examples/deprecation-guide/src/deprecated/app.component.html new file mode 100644 index 00000000000..f55801106fa --- /dev/null +++ b/aio/content/examples/deprecation-guide/src/deprecated/app.component.html @@ -0,0 +1,17 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/aio/content/examples/deprecation-guide/src/deprecated/app.component.ts b/aio/content/examples/deprecation-guide/src/deprecated/app.component.ts new file mode 100644 index 00000000000..526f739e581 --- /dev/null +++ b/aio/content/examples/deprecation-guide/src/deprecated/app.component.ts @@ -0,0 +1,39 @@ +// #docplaster +import { Component, ContentChild, Input, OnInit, TemplateRef } from '@angular/core'; +import { + FormControl, +} from '@angular/forms'; +@Component({ + selector: 'app-root', + templateUrl: './app.component.html' +}) +export class AppComponent implements OnInit { + title = 'example'; + value = 'initial value'; + control: FormControl = new FormControl(''); + options = [ + 'repeat-value' + ]; + + /* + // #docregion template-with-input-deprecated + @Input() @ContentChild(TemplateRef) tpldeprecated !: TemplateRef; + // #enddocregion template-with-input-deprecated + */ + + @Input() tpl !: TemplateRef; + @ContentChild(TemplateRef) inlineTemplate !: TemplateRef; + + ngOnInit() { + // #docregion deprecated-example + + this.value = 'some value'; + + // #enddocregion deprecated-example + this.setValue(); + } + + setValue(): void { + this.control.setValue('some value'); + } +} diff --git a/aio/content/examples/deprecation-guide/src/app/app.module.ts b/aio/content/examples/deprecation-guide/src/deprecated/app.module.ts similarity index 68% rename from aio/content/examples/deprecation-guide/src/app/app.module.ts rename to aio/content/examples/deprecation-guide/src/deprecated/app.module.ts index f3307e1875b..f8dee6f8836 100644 --- a/aio/content/examples/deprecation-guide/src/app/app.module.ts +++ b/aio/content/examples/deprecation-guide/src/deprecated/app.module.ts @@ -2,10 +2,27 @@ import { BrowserModule } from '@angular/platform-browser'; import { ModuleWithProviders, NgModule } from '@angular/core'; -import { AppComponent } from './app.component'; +import { AppComponent } from '../app/app.component'; import { FormsModule, ReactiveFormsModule } from '@angular/forms'; import { RouterModule, Routes } from '@angular/router'; -import { SubmitButtonComponent } from './submit-button/submit-button.component'; +import { SubmitButtonComponent } from '../app/submit-button.component'; + +// #docregion lazyload-syntax, lazyload-deprecated-syntax +const routes: Routes = [{ + path: 'lazy', + // #enddocregion lazyload-deprecated-syntax + // The new import() syntax + loadChildren: () => import('../app/lazy/lazy.module').then(m => m.LazyModule) + // #enddocregion lazyload-syntax + /* + // #docregion lazyload-deprecated-syntax + // The following string syntax for loadChildren is deprecated + loadChildren: './lazy/lazy.module#LazyModule', + // #enddocregion lazyload-deprecated-syntax + */ + // #docregion lazyload-syntax, lazyload-deprecated-syntax + }]; + // #enddocregion lazyload-syntax, lazyload-deprecated-syntax @NgModule({ declarations: [ diff --git a/aio/content/examples/deprecation-guide/src/app/lazy/lazy-routing.module.ts b/aio/content/examples/deprecation-guide/src/deprecated/lazy/lazy-routing.module.ts similarity index 100% rename from aio/content/examples/deprecation-guide/src/app/lazy/lazy-routing.module.ts rename to aio/content/examples/deprecation-guide/src/deprecated/lazy/lazy-routing.module.ts diff --git a/aio/content/examples/deprecation-guide/src/deprecated/lazy/lazy.component.ts b/aio/content/examples/deprecation-guide/src/deprecated/lazy/lazy.component.ts new file mode 100644 index 00000000000..f3835b8a702 --- /dev/null +++ b/aio/content/examples/deprecation-guide/src/deprecated/lazy/lazy.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'app-lazy', + template: `

lazy works!

` +}) +export class LazyComponent {} diff --git a/aio/content/examples/deprecation-guide/src/app/lazy/lazy.module.ts b/aio/content/examples/deprecation-guide/src/deprecated/lazy/lazy.module.ts similarity index 99% rename from aio/content/examples/deprecation-guide/src/app/lazy/lazy.module.ts rename to aio/content/examples/deprecation-guide/src/deprecated/lazy/lazy.module.ts index ea1272b5a24..ddd25eeaf5c 100644 --- a/aio/content/examples/deprecation-guide/src/app/lazy/lazy.module.ts +++ b/aio/content/examples/deprecation-guide/src/deprecated/lazy/lazy.module.ts @@ -4,7 +4,6 @@ import { CommonModule } from '@angular/common'; import { LazyRoutingModule } from './lazy-routing.module'; import { LazyComponent } from './lazy.component'; - @NgModule({ declarations: [ LazyComponent diff --git a/aio/content/examples/deprecation-guide/src/deprecated/readme.md b/aio/content/examples/deprecation-guide/src/deprecated/readme.md new file mode 100644 index 00000000000..8660310adb6 --- /dev/null +++ b/aio/content/examples/deprecation-guide/src/deprecated/readme.md @@ -0,0 +1,2 @@ +This `deprecated` directory holds examples of deprecated code reference in the docs, +all of them for an app built with NgModules. \ No newline at end of file diff --git a/aio/content/examples/deprecation-guide/src/main.ts b/aio/content/examples/deprecation-guide/src/main.ts index 0a621147e30..b22b12f3184 100644 --- a/aio/content/examples/deprecation-guide/src/main.ts +++ b/aio/content/examples/deprecation-guide/src/main.ts @@ -1,6 +1,6 @@ -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { bootstrapApplication } from '@angular/platform-browser'; -import { AppModule } from './app/app.module'; +import { AppComponent } from './app/app.component'; +import { appConfig } from './app/app.config'; -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); +bootstrapApplication(AppComponent, appConfig); diff --git a/aio/content/examples/displaying-data/BUILD.bazel b/aio/content/examples/displaying-data/BUILD.bazel deleted file mode 100644 index 9471286b3ce..00000000000 --- a/aio/content/examples/displaying-data/BUILD.bazel +++ /dev/null @@ -1,7 +0,0 @@ -load("//aio/content/examples:examples.bzl", "docs_example") - -package(default_visibility = ["//visibility:public"]) - -docs_example( - name = "displaying-data", -) diff --git a/aio/content/examples/displaying-data/e2e/src/app.e2e-spec.ts b/aio/content/examples/displaying-data/e2e/src/app.e2e-spec.ts deleted file mode 100644 index 6ede202dae8..00000000000 --- a/aio/content/examples/displaying-data/e2e/src/app.e2e-spec.ts +++ /dev/null @@ -1,25 +0,0 @@ -import { browser, element, by } from 'protractor'; - -describe('Displaying Data Tests', () => { - const title = 'Tour of Heroes'; - const defaultHero = 'Windstorm'; - - beforeAll(() => browser.get('')); - - it(`should display correct title: ${title}`, async () => { - expect(await element(by.css('h1')).getText()).toEqual(title); - }); - - it(`should have correct default hero: ${defaultHero}`, async () => { - expect(await element(by.css('h2')).getText()).toContain(defaultHero); - }); - - it('should have heroes', async () => { - const heroEls = element.all(by.css('li')); - expect(await heroEls.count()).not.toBe(0, 'should have heroes'); - }); - - it('should display "there are many heroes!"', async () => { - expect(await element(by.css('ul ~ p')).getText()).toContain('There are many heroes!'); - }); -}); diff --git a/aio/content/examples/displaying-data/example-config.json b/aio/content/examples/displaying-data/example-config.json deleted file mode 100644 index e69de29bb2d..00000000000 diff --git a/aio/content/examples/displaying-data/src/app/app-ctor.component.1.ts b/aio/content/examples/displaying-data/src/app/app-ctor.component.1.ts deleted file mode 100644 index 117bc3d86ab..00000000000 --- a/aio/content/examples/displaying-data/src/app/app-ctor.component.1.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-root', - template: ` -

{{title}} [Ctor version]

-

My favorite hero is: {{myHero}}

- ` -}) -export class AppComponent { - title = 'Tour of Heroes'; - myHero = 'Windstorm'; -} diff --git a/aio/content/examples/displaying-data/src/app/app.component.1.ts b/aio/content/examples/displaying-data/src/app/app.component.1.ts deleted file mode 100644 index 349f7028ae4..00000000000 --- a/aio/content/examples/displaying-data/src/app/app.component.1.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-root', - template: ` -

{{title}}

-

My favorite hero is: {{myHero}}

- ` -}) -export class AppComponent { - title = 'Tour of Heroes'; - myHero = 'Windstorm'; -} diff --git a/aio/content/examples/displaying-data/src/app/app.component.2.ts b/aio/content/examples/displaying-data/src/app/app.component.2.ts deleted file mode 100644 index 7b70d6ac1eb..00000000000 --- a/aio/content/examples/displaying-data/src/app/app.component.2.ts +++ /dev/null @@ -1,20 +0,0 @@ -import { Component } from '@angular/core'; - -@Component({ - selector: 'app-root', - template: ` -

{{title}}

-

My favorite hero is: {{myHero}}

-

Heroes:

-
    -
  • - {{ hero }} -
  • -
- ` -}) -export class AppComponent { - title = 'Tour of Heroes'; - heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado']; - myHero = this.heroes[0]; -} diff --git a/aio/content/examples/displaying-data/src/app/app.component.3.ts b/aio/content/examples/displaying-data/src/app/app.component.3.ts deleted file mode 100644 index c3ebc5c0906..00000000000 --- a/aio/content/examples/displaying-data/src/app/app.component.3.ts +++ /dev/null @@ -1,27 +0,0 @@ -import { Component } from '@angular/core'; - -import { Hero } from './hero'; - -@Component({ - selector: 'app-root', - template: ` -

{{title}}

-

My favorite hero is: {{myHero.name}}

-

Heroes:

-
    -
  • - {{ hero.name }} -
  • -
- ` -}) -export class AppComponent { - title = 'Tour of Heroes'; - heroes = [ - new Hero(1, 'Windstorm'), - new Hero(13, 'Bombasto'), - new Hero(15, 'Magneta'), - new Hero(20, 'Tornado') - ]; - myHero = this.heroes[0]; -} diff --git a/aio/content/examples/displaying-data/src/app/app.component.ts b/aio/content/examples/displaying-data/src/app/app.component.ts deleted file mode 100644 index de95f0adbbf..00000000000 --- a/aio/content/examples/displaying-data/src/app/app.component.ts +++ /dev/null @@ -1,28 +0,0 @@ -import { Component } from '@angular/core'; - -import { Hero } from './hero'; - -@Component({ - selector: 'app-root', - template: ` -

{{title}}

-

My favorite hero is: {{myHero.name}}

-

Heroes:

-
    -
  • - {{ hero.name }} -
  • -
-

There are many heroes!

-` -}) -export class AppComponent { - title = 'Tour of Heroes'; - heroes = [ - new Hero(1, 'Windstorm'), - new Hero(13, 'Bombasto'), - new Hero(15, 'Magneta'), - new Hero(20, 'Tornado') - ]; - myHero = this.heroes[0]; -} diff --git a/aio/content/examples/displaying-data/src/app/app.module.ts b/aio/content/examples/displaying-data/src/app/app.module.ts deleted file mode 100644 index 691b8c51fc2..00000000000 --- a/aio/content/examples/displaying-data/src/app/app.module.ts +++ /dev/null @@ -1,16 +0,0 @@ -// #docregion -import { NgModule } from '@angular/core'; -import { BrowserModule } from '@angular/platform-browser'; - -import { AppComponent } from './app.component'; - -@NgModule({ - imports: [ - BrowserModule - ], - declarations: [ - AppComponent - ], - bootstrap: [ AppComponent ] -}) -export class AppModule { } diff --git a/aio/content/examples/displaying-data/src/app/hero.ts b/aio/content/examples/displaying-data/src/app/hero.ts deleted file mode 100644 index 27671db0bbc..00000000000 --- a/aio/content/examples/displaying-data/src/app/hero.ts +++ /dev/null @@ -1,5 +0,0 @@ -export class Hero { - constructor( - public id: number, - public name: string) { } -} diff --git a/aio/content/examples/displaying-data/src/index.html b/aio/content/examples/displaying-data/src/index.html deleted file mode 100644 index 6f42a6a510b..00000000000 --- a/aio/content/examples/displaying-data/src/index.html +++ /dev/null @@ -1,13 +0,0 @@ - - - - Displaying Data - - - - - - - - - diff --git a/aio/content/examples/displaying-data/src/main.ts b/aio/content/examples/displaying-data/src/main.ts deleted file mode 100644 index 49432aa0877..00000000000 --- a/aio/content/examples/displaying-data/src/main.ts +++ /dev/null @@ -1,7 +0,0 @@ -// #docregion -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; - -import { AppModule } from './app/app.module'; - -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); diff --git a/aio/content/examples/displaying-data/stackblitz.json b/aio/content/examples/displaying-data/stackblitz.json deleted file mode 100644 index 75b223fea58..00000000000 --- a/aio/content/examples/displaying-data/stackblitz.json +++ /dev/null @@ -1,11 +0,0 @@ -{ - "description": "Displaying Data", - "files": [ - "!**/*.d.ts", - "!**/*.js", - "!**/app-ctor.component.ts", - "!**/*.[1,2,3].*" - ], - "file": "src/app/app.component.ts", - "tags": ["Template"] -} diff --git a/aio/content/examples/examples.bzl b/aio/content/examples/examples.bzl index a7f389f4ac2..94bdaa66814 100644 --- a/aio/content/examples/examples.bzl +++ b/aio/content/examples/examples.bzl @@ -36,7 +36,6 @@ EXAMPLES = { "dependency-injection": {"stackblitz": True, "zip": True}, "dependency-injection-in-action": {"stackblitz": True, "zip": True}, "deprecation-guide": {"stackblitz": True, "zip": True}, - "displaying-data": {"stackblitz": True, "zip": True}, "docs-style-guide": {"stackblitz": True, "zip": True}, "dynamic-component-loader": {"stackblitz": True, "zip": True}, "dynamic-form": {"stackblitz": True, "zip": True}, diff --git a/aio/content/examples/ngcontainer/src/app/app.component.html b/aio/content/examples/ngcontainer/src/app/app.component.html index 1185b801358..afc9cb5659a 100644 --- a/aio/content/examples/ngcontainer/src/app/app.component.html +++ b/aio/content/examples/ngcontainer/src/app/app.component.html @@ -1,5 +1,3 @@ - -

<ng-container>

{{hero.name}}
diff --git a/aio/content/examples/ngcontainer/src/app/app.component.ts b/aio/content/examples/ngcontainer/src/app/app.component.ts index b17014d6a3b..8b76140424c 100644 --- a/aio/content/examples/ngcontainer/src/app/app.component.ts +++ b/aio/content/examples/ngcontainer/src/app/app.component.ts @@ -1,11 +1,16 @@ -// #docregion import { Component } from '@angular/core'; +import { NgIf, NgFor, UpperCasePipe } from '@angular/common'; +import { FormsModule } from '@angular/forms'; + +import { ContentComponent } from './content.component'; import { Hero, heroes } from './hero'; @Component({ + standalone: true, selector: 'app-root', templateUrl: './app.component.html', + imports: [ContentComponent, FormsModule, NgIf, NgFor, UpperCasePipe], styleUrls: ['./app.component.css'] }) export class AppComponent { diff --git a/aio/content/examples/ngcontainer/src/app/app.module.ts b/aio/content/examples/ngcontainer/src/app/app.module.ts deleted file mode 100644 index f18ebb526ed..00000000000 --- a/aio/content/examples/ngcontainer/src/app/app.module.ts +++ /dev/null @@ -1,19 +0,0 @@ -// #docregion -import { NgModule } from '@angular/core'; -import { FormsModule } from '@angular/forms'; -import { BrowserModule } from '@angular/platform-browser'; - -import { AppComponent } from './app.component'; -import { ContentComponent } from './content.component'; -import { heroComponents } from './hero.components'; - -@NgModule({ - imports: [ BrowserModule, FormsModule ], - declarations: [ - AppComponent, - ContentComponent, - heroComponents - ], - bootstrap: [ AppComponent ] -}) -export class AppModule { } diff --git a/aio/content/examples/ngcontainer/src/app/content.component.ts b/aio/content/examples/ngcontainer/src/app/content.component.ts index bb3af9c040a..5f93435398d 100644 --- a/aio/content/examples/ngcontainer/src/app/content.component.ts +++ b/aio/content/examples/ngcontainer/src/app/content.component.ts @@ -1,6 +1,7 @@ import { Component } from '@angular/core'; @Component({ + standalone: true, selector: 'content-comp', template: `
diff --git a/aio/content/examples/ngcontainer/src/app/hero.components.ts b/aio/content/examples/ngcontainer/src/app/hero.components.ts index 48205c8f7f1..343f13f9d0b 100644 --- a/aio/content/examples/ngcontainer/src/app/hero.components.ts +++ b/aio/content/examples/ngcontainer/src/app/hero.components.ts @@ -1,9 +1,9 @@ -// #docregion import { Component, Input } from '@angular/core'; import { Hero } from './hero'; @Component({ + standalone: true, selector: 'happy-hero', template: 'Wow. You like {{hero.name}}. What a happy hero ... just like you.' }) @@ -12,6 +12,7 @@ export class HappyHeroComponent { } @Component({ + standalone: true, selector: 'sad-hero', template: 'You like {{hero.name}}? Such a sad hero. Are you sad too?' }) @@ -20,6 +21,7 @@ export class SadHeroComponent { } @Component({ + standalone: true, selector: 'confused-hero', template: 'Are you as confused as {{hero.name}}?' }) @@ -28,6 +30,7 @@ export class ConfusedHeroComponent { } @Component({ + standalone: true, selector: 'unknown-hero', template: '{{message}}' }) diff --git a/aio/content/examples/ngcontainer/src/main.ts b/aio/content/examples/ngcontainer/src/main.ts index 49432aa0877..5a2dcb1b362 100644 --- a/aio/content/examples/ngcontainer/src/main.ts +++ b/aio/content/examples/ngcontainer/src/main.ts @@ -1,7 +1,9 @@ -// #docregion -import { platformBrowserDynamic } from '@angular/platform-browser-dynamic'; +import { bootstrapApplication, provideProtractorTestingSupport } from '@angular/platform-browser'; -import { AppModule } from './app/app.module'; +import {AppComponent} from './app/app.component'; -platformBrowserDynamic().bootstrapModule(AppModule) - .catch(err => console.error(err)); +bootstrapApplication(AppComponent, { + providers: [ + provideProtractorTestingSupport(), // essential for e2e testing + ] +}); diff --git a/aio/content/guide/ajs-quick-reference.md b/aio/content/guide/ajs-quick-reference.md index e952e2dab96..19dd16b1e73 100644 --- a/aio/content/guide/ajs-quick-reference.md +++ b/aio/content/guide/ajs-quick-reference.md @@ -42,7 +42,7 @@ The following are some of the key AngularJS built-in directives and their equiva | AngularJS | Angular | |:--- |:--- | -|
ng-app
<body ng-app="movieHunter"> The application startup process is called **bootstrapping**.
Although you can bootstrap an AngularJS application in code, many applications bootstrap declaratively with the `ng-app` directive, giving it the name of the module \(`movieHunter`\) of the application. |
Bootstrapping
Angular does not have a bootstrap directive. To launch the application in code, explicitly bootstrap the root module \(`AppModule`\) of the application in `main.ts` and the root component \(`AppComponent`\) of the application in `app.module.ts`. | +|
ng-app
<body ng-app="movieHunter"> The application startup process is called **bootstrapping**.
Although you can bootstrap an AngularJS application in code, many applications bootstrap declaratively with the `ng-app` directive, giving it the name of the module \(`movieHunter`\) of the application. |
Bootstrapping
Angular does not have a bootstrap directive. To launch the application in code, explicitly bootstrap the application's root component \(`AppComponent`\) in `main.ts`.| ### `ng-class` → `ngClass` @@ -170,12 +170,11 @@ For more information on pipes, see [Pipes][AioGuidePipes]. |:--- |:--- | |
orderBy
<tr ng-repeat="movie in movieList | orderBy : 'title'"> Displays the collection in the order specified by the expression. In this example, the movie title orders the `movieList`. |
none
For performance reasons, no comparable pipe exists in Angular. Instead, use component code to order or sort results. If you need the same ordering or sorting code in several templates, consider building a custom pipe. | -## Modules / controllers / components - -In both AngularJS and Angular, modules help you organize your application into cohesive blocks of features. +## Controllers and Components In AngularJS, you write the code that provides the model and the methods for the view in a **controller**. -In Angular, you build a **component**. + +In Angular, you build a **component** which typically acquires its model from an **injected service**. Because much AngularJS code is in JavaScript, JavaScript code is shown in the AngularJS column. The Angular code is shown using TypeScript. @@ -184,25 +183,21 @@ The Angular code is shown using TypeScript. | AngularJS | Angular | |:--- |:--- | -|
IIFE
(   function () {     …   }() ); In AngularJS, an IIFE around controller code keeps it out of the global namespace. |
none
This is a nonissue in Angular because ES 2015 modules handle the namespace for you.
For more information on modules, see the [Modules][AioGuideArchitectureModules] section of the [Architecture Overview][AioGuideArchitecture]. | +|
IIFE
(   function () {     …   }() ); In AngularJS, an IIFE around controller code keeps it out of the global namespace. |
none
This is a nonissue in Angular because ES 2015 modules handle the namespace for you. | -### Angular modules → `NgModules` -| AngularJS | Angular | -|:--- |:--- | -|
Angular modules
angular .module(   "movieHunter",   [     "ngRoute"   ] ); In AngularJS, an Angular module keeps track of controllers, services, and other code. The second argument defines the list of other modules that this module depends upon. |
NgModules
NgModules, defined with the `NgModule` decorator, serve the same purpose:
  • `imports`: specifies the list of other modules that this module depends upon
  • `declaration`: keeps track of your components, pipes, and directives.
For more information on modules, see [NgModules][AioGuideNgmodules]. | ### Controller registration → component decorator | AngularJS | Angular | |:--- |:--- | -|
Controller registration
angular .module(   "movieHunter" ) .controller(   "MovieListCtrl",   [     "movieService",     MovieListCtrl   ] ); AngularJS has code in each controller that looks up an appropriate Angular module and registers the controller with that module.
The first argument is the controller name. The second argument defines the string names of all dependencies injected into this controller, and a reference to the controller function. |
Component decorator
Angular adds a decorator to the component class to provide any required metadata. The `@Component` decorator declares that the class is a component and provides metadata about that component such as its selector, or tag, and its template.
This is how you associate a template with logic, which is defined in the component class.
For more information, see the [Components][AioGuideArchitectureComponents] section of the [Architecture Overview][AioGuideArchitecture] page. | +|
Controller registration
angular .module(   "movieHunter" ) .controller(   "MovieListCtrl",   [     "movieService",     MovieListCtrl   ] ); AngularJS has code in each controller that looks up an appropriate AngularJS module and registers the controller with that module.
The first argument is the controller name. The second argument defines the string names of all dependencies injected into this controller, and a reference to the controller function. |
Component decorator
Angular adds a decorator to the component class to provide any required metadata. The `@Component` decorator declares that the class is a component and provides metadata about that component such as its selector, or tag, and its template.
This is how you associate a template with logic, which is defined in the component class.
For more information, see the [Components][AioGuideArchitectureComponents] section of the [Architecture Overview][AioGuideArchitecture] page. | ### Controller function → component class | AngularJS | Angular | |:--- |:--- | -|
Controller function
function MovieListCtrl(movieService) { } In AngularJS, you write the code for the model and methods in a controller function. |
Component class
In Angular, you create a component class to contain the data model and control methods. Use the TypeScript export keyword to export the class so that the component can be imported into NgModules.
For more information, see the [Components][AioGuideArchitectureComponents] section of the [Architecture Overview][AioGuideArchitecture] page. | +|
Controller function
function MovieListCtrl(movieService) { } In AngularJS, you write the code for the model and methods in a controller function. |
Component class
In Angular, you create a component class to contain the data model and control methods. Use the TypeScript export keyword to export the class so that the component can be imported into other classes.
For more information, see the [Components][AioGuideArchitectureComponents] section of the [Architecture Overview][AioGuideArchitecture] page. | ### Dependency injection → dependency injection @@ -234,7 +229,7 @@ Now you can also encapsulate a style sheet within a specific component. [AioGuideArchitecture]: guide/architecture "Introduction to Angular concepts | Angular" [AioGuideArchitectureComponents]: guide/architecture#components "Components - Introduction to Angular concepts | Angular" -[AioGuideArchitectureModules]: guide/architecture#modules "Modules - Introduction to Angular concepts | Angular" + [AioGuideArchitectureServicesAndDependencyInjection]: guide/architecture#services-and-dependency-injection "Services and dependency injection - Introduction to Angular concepts | Angular" [AioGuideAttributeBinding]: guide/attribute-binding "Attribute, class, and style bindings | Angular" @@ -249,9 +244,7 @@ Now you can also encapsulate a style sheet within a specific component. [AioGuideInterpolation]: guide/interpolation "Text interpolation | Angular" -[AioGuideNgmodules]: guide/ngmodules "NgModules | Angular" - -[AioGuidePipes]: guide/pipes-overview "Transforming Data Using Pipes | Angular" +[AioGuidePipes]: guide/pipes "Transforming Data Using Pipes | Angular" [AioGuidePropertyBinding]: guide/property-binding "Property binding | Angular" @@ -267,4 +260,4 @@ Now you can also encapsulate a style sheet within a specific component. -@reviewed 2023-08-14 +@reviewed 2023-09-25 diff --git a/aio/content/guide/architecture-components.md b/aio/content/guide/architecture-components.md index 8758884ec7b..07e2cce60e2 100644 --- a/aio/content/guide/architecture-components.md +++ b/aio/content/guide/architecture-components.md @@ -50,8 +50,10 @@ This example shows some of the most useful `@Component` configuration options: | Configuration options | Details | |:--- |:--- | +| `standalone` | `true` when this is a self-describing, ["Standalone"](guide/standalone-components) component. If `false` or unspecified, the component must be declared in an [ngModule](guide/ngmodules) which is an older style. Prefer `true` if you can. | | `selector` | A CSS selector that tells Angular to create and insert an instance of this component wherever it finds the corresponding tag in template HTML. For example, if an application's HTML contains ``, then Angular inserts an instance of the `HeroListComponent` view between those tags. | -| `templateUrl` | The module-relative address of this component's HTML template. Alternatively, you can provide the HTML template inline, as the value of the `template` property. This template defines the component's *host view*. | +| `templateUrl` | The relative address of this component's HTML template. Alternatively, you can provide the HTML template inline, as the value of the `template` property. This template defines the component's *host view*. | +| `imports` | An array of the components, directives, and packages that your template references. Essential for "Standalone" components. | | `providers` | An array of [providers](guide/glossary#provider) for services that the component requires. In the example, this tells Angular how to provide the `HeroService` instance that the component's constructor uses to get the list of heroes to display. | ## Templates and views @@ -75,8 +77,6 @@ The component can also define a *view hierarchy*, which contains *embedded views
-A view hierarchy can include views from components in the same NgModule and from those in different NgModules. - ## Template syntax A template looks like regular HTML, except that it also contains Angular [template syntax](guide/template-syntax), which alters the HTML based on your application's logic and the state of application and DOM data. @@ -242,4 +242,4 @@ Learn more in the [Attribute Directives](guide/attribute-directives) and [Struct -@reviewed 2023-08-14 +@reviewed 2023-09-25 diff --git a/aio/content/guide/architecture-modules.md b/aio/content/guide/architecture-modules.md index 5b467775d7e..cfda2185dd2 100644 --- a/aio/content/guide/architecture-modules.md +++ b/aio/content/guide/architecture-modules.md @@ -1,13 +1,20 @@ # Introduction to modules Angular applications are modular and Angular has its own modularity system called *NgModules*. + +
+ +Older Angular applications are built with `NgModules`. +While this is no longer the preferred approach, many existing applications are still built with `NgModules`. + +This page offers an overview of that concept; [learn more here](guide/ngmodules). + +
+ NgModules are containers for a cohesive block of code dedicated to an application domain, a workflow, or a closely related set of capabilities. They can contain components, service providers, and other code files whose scope is defined by the containing NgModule. They can import functionality that is exported from other NgModules, and export selected functionality for use by other NgModules. -Every Angular application has at least one NgModule class, [the *root module*](guide/bootstrapping), which is conventionally named `AppModule` and resides in a file named `app.module.ts`. -You launch your application by *bootstrapping* the root NgModule. - While a small application might have only one NgModule, most applications have many more *feature modules*. The *root* NgModule for an application is so named because it can include child NgModules in a hierarchy of any depth. @@ -84,9 +91,9 @@ In JavaScript each *file* is a module and all objects defined in the file belong The module declares some objects to be public by marking them with the `export` key word. Other JavaScript modules use *import statements* to access public objects from other modules. - + - +
diff --git a/aio/content/guide/architecture-next-steps.md b/aio/content/guide/architecture-next-steps.md index 2fe7495119c..ace0f61fb65 100644 --- a/aio/content/guide/architecture-next-steps.md +++ b/aio/content/guide/architecture-next-steps.md @@ -10,7 +10,6 @@ about the features and tools that can help you develop and deliver Angular appli ## Application architecture * The **Main Concepts** section located in the table of contents contains several topics that explain how to connect the application data in your [components](guide/glossary#component) to your page-display [templates](guide/glossary#template), to create a complete interactive application. -* The [NgModules](guide/ngmodules) guide provides in-depth information on the modular structure of an Angular application. * The [Routing and navigation](guide/router) guide provides in-depth information on how to construct applications that allow a user to navigate to different [views](guide/glossary#view) within your single-page application. * The [Dependency injection](guide/dependency-injection) guide provides in-depth information on how to construct an application such that each component class can acquire the services and objects it needs to perform its function. @@ -70,4 +69,4 @@ For some platforms and applications, you might also want to use the PWA \(Progre -@reviewed 2022-02-28 +@reviewed 2023-09-25 diff --git a/aio/content/guide/architecture-services.md b/aio/content/guide/architecture-services.md index 38d78a5d135..c770ad1c976 100644 --- a/aio/content/guide/architecture-services.md +++ b/aio/content/guide/architecture-services.md @@ -38,22 +38,21 @@ That service in turn might depend on the `HttpClient` service to fetch heroes as Dependency injection (DI) is the part of the Angular framework that provides components with access to services and other resources. Angular provides the ability for you to *inject* a service into a component to give that component access to the service. -The `@Injectable()` decorator defines a class as a service in Angular and allows Angular to inject it into a component as a *dependency*. -Likewise, the `@Injectable()` decorator indicates that a component, class, pipe, or NgModule *has* a dependency on a service. +Add the `@Injectable()` decorator to a service class so that Angular can inject it into a component as a *dependency*; the optional argument tells Angular where to register this class by default. -* The *injector* is the main mechanism. - Angular creates an application-wide injector for you during the bootstrap process, and additional injectors as needed. - You don't have to create injectors. + + -* An injector creates dependencies and maintains a *container* of dependency instances that it reuses, if possible. -* A *provider* is an object that tells an injector how to obtain or create a dependency +* Something *injectable* must be registered with an *injector* before it can be created and used. + +* Register an injectable with a *provider*, an object that tells an injector how to obtain or create a dependency. For a service class, the provider is typically the class itself. + +* You don't have to create injectors. Under the hood Angular creates an application-wide *root injector* for you during the bootstrap process. It creates additional child injectors as needed. -For any dependency that you need in your app, you must register a provider with the application's injector, so that the injector can use the provider to create new instances. -For a service, the provider is typically the service class itself.
-A dependency doesn't have to be a service —it could be a function, for example, or a value. +An injectable dependency doesn't have to be a class — it could be a function, for example, or a value.
@@ -78,18 +77,13 @@ The process of `HeroService` injection looks something like this. ### Providing services You must register at least one *provider* of any service you are going to use. -The provider can be part of the service's own metadata, making that service available everywhere, or you can register providers with specific modules or components. -You register providers in the metadata of the service \(in the `@Injectable()` decorator\), or in the `@NgModule()` or `@Component()` metadata +The provider can be part of the service's own metadata, making that service available everywhere, or you can register providers with specific components. +You register providers in the metadata of the service \(in the `@Injectable()` decorator\) or `@Component()` metadata * By default, the Angular CLI command [`ng generate service`](cli/generate) registers a provider with the root injector for your service by including provider metadata in the `@Injectable()` decorator. - The tutorial uses this method to register the provider of HeroService class definition. - - - - @Injectable({ - providedIn: 'root', - }) + The tutorial uses this method to register the provider of `HeroService` class definition. + When you provide the service at the root level, Angular creates a single, shared instance of `HeroService` @@ -97,21 +91,6 @@ You register providers in the metadata of the service \(in the `@Injectable()` d Registering the provider in the `@Injectable()` metadata also allows Angular to optimize an app by removing the service from the compiled application if it isn't used, a process known as *tree-shaking*. -* When you register a provider with a [specific NgModule](guide/architecture-modules), the same instance of a service is available to all components in that NgModule. - To register at this level, use the `providers` property of the `@NgModule()` decorator. - - - - @NgModule({ - providers: [ - BackendService, - Logger - ], - … - }) - - - * When you register a provider at the component level, you get a new instance of the service with each new instance of that component. At the component level, register a service provider in the `providers` property of the `@Component()` metadata. @@ -125,4 +104,4 @@ For more detailed information, see the [Dependency Injection](guide/dependency-i -@reviewed 2022-02-28 +@reviewed 2023-09-25 diff --git a/aio/content/guide/architecture.md b/aio/content/guide/architecture.md index 24107a2e51b..8d71c1d8188 100644 --- a/aio/content/guide/architecture.md +++ b/aio/content/guide/architecture.md @@ -5,16 +5,15 @@ Angular is written in TypeScript. It implements core and optional functionality as a set of TypeScript libraries that you import into your applications. The architecture of an Angular application relies on certain fundamental concepts. -The basic building blocks of the Angular framework are Angular components that are organized into *NgModules*. -NgModules collect related code into functional sets; an Angular application is defined by a set of NgModules. -An application always has at least a *root module* that enables bootstrapping, and typically has many more *feature modules*. +The basic building blocks of the Angular framework are Angular components. -* Components define *views*, which are sets of screen elements that Angular can choose among and modify according to your program logic and data -* Components use *services*, which provide specific functionality not directly related to views. - Service providers can be *injected* into components as *dependencies*, making your code modular, reusable, and efficient. +Components define *views*, which are sets of screen elements that Angular can choose among and modify according to your program logic and data -Modules, components and services are classes that use *decorators*. -These decorators mark their type and provide metadata that tells Angular how to use them. +Components use *services*, which provide background functionality not directly related to views such as fetching data. +Such services can be *injected* into components as *dependencies*, making your code modular, reusable, and efficient. + +Components and services are classes marked with *decorators*. +These decorators provide metadata that tells Angular how to use them. * The metadata for a component class associates it with a *template* that defines a view. A template combines ordinary HTML with Angular *directives* and *binding markup* that allow Angular to modify the HTML before rendering it for display. @@ -37,27 +36,6 @@ For the sample application that this page describes, see the -## Modules - -Angular *NgModules* differ from and complement JavaScript \(ES2015\) modules. -An NgModule declares a compilation context for a set of components that is dedicated to an application domain, a workflow, or a closely related set of capabilities. -An NgModule can associate its components with related code, such as services, to form functional units. - -Every Angular application has a *root module*, conventionally named `AppModule`, which provides the bootstrap mechanism that launches the application. -An application typically contains many functional modules. - -Like JavaScript modules, NgModules can import functionality from other NgModules, and allow their own functionality to be exported and used by other NgModules. -For example, to use the router service in your app, you import the `Router` NgModule. - -Organizing your code into distinct functional modules helps in managing development of complex applications, and in designing for reusability. -In addition, this technique lets you take advantage of *lazy-loading* —that is, loading modules on demand— to minimize the amount of code that needs to be loaded at startup. - -
- -For a more detailed discussion, see [Introduction to modules](guide/architecture-modules). - -
- ## Components Every Angular application has at least one component, the *root component* that connects a component hierarchy with the page document object model \(DOM\). @@ -117,17 +95,17 @@ For a more detailed discussion, see [Introduction to services and DI](guide/arch ### Routing -The Angular `Router` NgModule provides a service that lets you define a navigation path among the different application states and view hierarchies in your application. +The Angular `Router` package provides a service that lets you define a navigation path among the different application states and view hierarchies in your application. It is modeled on the familiar browser navigation conventions: * Enter a URL in the address bar and the browser navigates to a corresponding page * Click links on the page and the browser navigates to a new page * Click the browser's back and forward buttons and the browser navigates backward and forward through the history of pages you've seen -The router maps URL-like paths to views instead of pages. -When a user performs an action, such as clicking a link, that would load a new page in the browser, the router intercepts the browser's behavior, and shows or hides view hierarchies. +The router maps URL-like paths to components instead of pages. +When a user performs an action, such as clicking a link, that would load a new component in the browser, the router intercepts the browser's behavior, and shows or hides that component (and its child components). -If the router determines that the current application state requires particular functionality, and the module that defines it hasn't been loaded, the router can *lazy-load* the module on demand. +If the router determines that the current application state requires a component that hasn't been loaded, the router can *lazy-load* that component and its related dependencies. The router interprets a link URL according to your application's view navigation rules and data state. You can navigate to new views when the user clicks a button or selects from a drop box, or in response to some other stimulus from any source. @@ -145,23 +123,9 @@ For a more detailed discussion, see [Routing and navigation](guide/router). ## What's next -You've learned the basics about the main building blocks of an Angular application. -The following diagram shows how these basic pieces are related. +You've discovered the main building blocks of an Angular application. +Learn a bit more about them in the following architecture pages. - - -* Together, a component and template define an Angular view - * A decorator on a component class adds the metadata, including a pointer to the associated template - * Directives and binding markup in a component's template modify views based on program data and logic -* The dependency injector provides services to a component, such as the router service that lets you define navigation among views - -Each of these subjects is introduced in more detail in the following pages. - -* [Introduction to Modules](guide/architecture-modules) * [Introduction to Components](guide/architecture-components) * [Templates and views](guide/architecture-components#templates-and-views) * [Component metadata](guide/architecture-components#component-metadata) @@ -170,8 +134,9 @@ Each of these subjects is introduced in more detail in the following pages. * [Pipes](guide/architecture-components#pipes) * [Introduction to services and dependency injection](guide/architecture-services) -When you're familiar with these fundamental building blocks, you can explore them in more detail in the documentation. -To learn about more tools and techniques that are available to help you build and deploy Angular applications, see [Next steps: tools and techniques](guide/architecture-next-steps). +When you're familiar with these fundamental building blocks, you can explore them in greater detail in the documentation. + +You may also be interested in [tools and techniques](guide/architecture-next-steps) to help you build and deploy Angular applications.
@@ -181,4 +146,4 @@ To learn about more tools and techniques that are available to help you build an -@reviewed 2022-02-28 +@reviewed 2023-09-25 diff --git a/aio/content/guide/deprecations.md b/aio/content/guide/deprecations.md index 223623a5728..d4ecfd3c766 100644 --- a/aio/content/guide/deprecations.md +++ b/aio/content/guide/deprecations.md @@ -324,9 +324,9 @@ Support for using the `ngModel` input property and `ngModelChange` event with re Now deprecated: - + - + This support was deprecated for several reasons. First, developers found this pattern confusing. @@ -338,13 +338,14 @@ Setting the value in the template violates the template-agnostic principles behi To update your code before support is removed, decide whether to stick with reactive form directives \(and get/set values using reactive forms patterns\) or switch to template-driven directives. -**After** \(choice 1 - use reactive forms\): +**After** \(choice 1 - with reactive forms\): - + + -**After** \(choice 2 - use template-driven forms\): +**After** \(choice 2 - with template-driven forms\): @@ -353,7 +354,7 @@ To update your code before support is removed, decide whether to stick with reac By default, when you use this pattern, you get a deprecation warning once in dev mode. You can choose to silence this warning by configuring `ReactiveFormsModule` at import time: - + Alternatively, you can choose to surface a separate warning for each instance of this pattern with a configuration value of `"always"`. This may help to track down where in the code the pattern is being used as the code is being updated. @@ -422,16 +423,18 @@ 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`: +application strategy in DI via the `providers` in the configuration of `boostrapApplication()` for a "Standalone" app or +in the root `app.module` of an NgModule app: * `routeReuseStrategy` -The following options are meant to be configured using the options -available in `RouterModule.forRoot` or `provideRouter` and `withRouterConfig`. +The following options are meant to be configured using the options object +of `withRouterConfig()` passed to `provideRouter` for a "Standalone" app or +passed to `RouterModule.forRoot()` in the root `app.module` of an NgModule app: * `onSameUrlNavigation` * `errorHandler` -The following options are deprecated in entirely: +The following options are deprecated entirely: +* `malformedUriErrorHandler` - URI parsing errors should be handled in the `UrlSerializer` instead. * `errorHandler` - Subscribe to the `Router` events and filter for `NavigationError` instead. @@ -444,6 +447,51 @@ matched at all and also prevent loading the children of the `Route`. `CanMatch` goals as `CanLoad` but with the addition of allowing the navigation to match other routes when they reject (such as a wildcard route). There is no need to have both types of guards in the API surface. + + +### `loadChildren` string syntax (NgModule) + +
+ +This deprecation notice applies only to lazy loading of [NgModules](guide/ngmodules). + +["Standalone"](guide/standalone-components) applications do not reference modules. +They can lazy load a component with `loadComponent` +or an array of child routes with `loadChildren` as +[discussed here](guide/standalone-components#routing-and-lazy-loading). + +
+ +When Angular first introduced lazy routes, there wasn't browser support for dynamically loading additional JavaScript. +Angular created its own scheme using the syntax `loadChildren: './lazy/lazy.module#LazyModule'` and built tooling to support it. +Now that ECMAScript dynamic import is supported in many browsers, Angular is moving toward this new syntax. + +In version 8, the string syntax for the [`loadChildren`](api/router/LoadChildren) route specification was deprecated, in favor of new syntax that uses `import()` syntax. + +**Before**: + + + +**After**: + + + +
+ +**Version 8 update**: When you update to version 8, the [`ng update`](cli/update) command performs the transformation automatically. +Prior to version 7, the `import()` syntax only works in JIT mode \(with view engine\). + +
+ +
+ +**Declaration syntax**:
+It's important to follow the route declaration syntax `loadChildren: () => import('...').then(m => m.ModuleName)` to allow `ngc` to discover the lazy-loaded module and the associated `NgModule`. +You can find the complete list of allowed syntax constructs [here](https://github.com/angular/angular-cli/blob/a491b09800b493fe01301387fa9a025f7c7d4808/packages/ngtools/webpack/src/transformers/import_factory.ts#L104-L113). +These restrictions will be relaxed with the release of Ivy since it'll no longer use `NgFactories`. + +
+ ### Dependency on a reflect-metadata polyfill in JIT mode @@ -469,7 +517,7 @@ See the [dedicated migration guide for static queries](guide/static-query-migrat The following pattern is deprecated: - + Rather than using this pattern, separate the two decorators into their own properties and add fallback logic as in the following example: @@ -483,7 +531,7 @@ properties and add fallback logic as in the following example: In the following example, the two-way binding means that `optionName` should be written when the `valueChange` event fires. - + However, in practice, Angular ignores two-way bindings to template variables. Starting in version 8, attempting to write to template variables is deprecated. @@ -537,29 +585,11 @@ For example: **Before**: - + **After**: - - - + @@ -575,11 +605,11 @@ This means that input coercion fields are no longer needed, as their effects can For example, the following directive: - + can be refactored as follows: - + @@ -711,4 +741,4 @@ If you rely on the behavior that the same object instance should cause change de -@reviewed 2023-05-03 +@reviewed 2023-09-26 diff --git a/aio/content/guide/glossary.md b/aio/content/guide/glossary.md index 42d2b5cb6f0..b2fea04d25d 100644 --- a/aio/content/guide/glossary.md +++ b/aio/content/guide/glossary.md @@ -702,7 +702,7 @@ You can also use the `schematics` command to add a new schematic to an existing ## scoped package A way to group related [npm packages][AioGuideNpmPackages]. -NgModules are delivered within scoped packages whose names begin with the Angular *scope name* `@angular`. +Angular objects are delivered from npm packages whose names begin with the Angular *scope name* `@angular`. For example, `@angular/core`, `@angular/common`, `@angular/forms`, and `@angular/router`. Import a scoped package in the same way that you import a normal package. diff --git a/aio/content/guide/lazy-loading-ngmodules.md b/aio/content/guide/lazy-loading-ngmodules.md index ebaec2eca1f..e2e1e683c46 100644 --- a/aio/content/guide/lazy-loading-ngmodules.md +++ b/aio/content/guide/lazy-loading-ngmodules.md @@ -98,6 +98,17 @@ Instead, it adds the declared route, `customers` to the `routes` array declared Notice that the lazy-loading syntax uses `loadChildren` followed by a function that uses the browser's built-in `import('...')` syntax for dynamic imports. The import path is the relative path to the module. +
+ +
String-based lazy loading
+ +In Angular version 8, the string syntax for the `loadChildren` route specification [was deprecated](guide/deprecations#loadChildren) in favor of the `import()` syntax. +You can opt into using string-based lazy loading \(`loadChildren: './path/to/module#Module'`\) by including the lazy-loaded routes in your `tsconfig` file, which includes the lazy-loaded files in the compilation. + +By default the Angular CLI generates projects with stricter file inclusions intended to be used with the `import()` syntax. + +
+ ### Add another feature module Use the same command to create a second lazy-loaded feature module with routing, along with its stub component. diff --git a/aio/content/guide/zone.md b/aio/content/guide/zone.md index e824b047184..3fb30118852 100644 --- a/aio/content/guide/zone.md +++ b/aio/content/guide/zone.md @@ -14,9 +14,13 @@ To understand the benefits of `NgZone`, it is important to have a clear grasp of ### Displaying and updating data in Angular -In Angular, you can display data by binding controls in an HTML template to the properties of an Angular component. +In Angular, you can display data by projecting the values of Angular component properties into an HTML template. - + + +<label>My favorite hero is {{hero.name}}</label> + + You can also bind DOM events to a method of an Angular component. In such methods, you can also update a property of the Angular component, which updates the corresponding data displayed in the template. @@ -496,4 +500,4 @@ To remove Zone.js, make the following changes. -@reviewed 2022-02-28 +@reviewed 2023-09-26 diff --git a/aio/content/navigation.json b/aio/content/navigation.json index ab8cbbe26c9..1dc9973d667 100644 --- a/aio/content/navigation.json +++ b/aio/content/navigation.json @@ -1123,11 +1123,6 @@ "title": "Intro to basic concepts", "tooltip": "Basic building blocks of Angular applications." }, - { - "url": "guide/architecture-modules", - "title": "Intro to modules", - "tooltip": "About NgModules." - }, { "url": "guide/architecture-components", "title": "Intro to components", @@ -1138,11 +1133,6 @@ "title": "Intro to services and DI", "tooltip": "About services and dependency injection." }, - { - "url": "guide/architecture-next-steps", - "title": "Next steps", - "tooltip": "Beyond the basics." - }, { "url": "guide/binding-syntax", "title": "Binding syntax", @@ -1157,6 +1147,11 @@ "url": "guide/template-reference-variables", "title": "Template variables", "tooltip": "Introductory guide to referring to DOM elements within a template." + }, + { + "url": "guide/architecture-next-steps", + "title": "Next steps", + "tooltip": "Beyond the basics." } ] },