mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
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
This commit is contained in:
committed by
Pawel Kozlowski
parent
8e5d54a3d5
commit
e90f5e5f22
@@ -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 {}
|
||||
@@ -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 {
|
||||
|
||||
|
||||
@@ -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
|
||||
],
|
||||
};
|
||||
@@ -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 { }
|
||||
@@ -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 { }
|
||||
@@ -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
|
||||
|
||||
@@ -2,7 +2,7 @@ import { Injectable } from '@angular/core';
|
||||
|
||||
import { IMovie } from './movie';
|
||||
|
||||
@Injectable()
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class MovieService {
|
||||
getMovies(): IMovie[] {
|
||||
return [
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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: `
|
||||
<h1>Architecture Example</h1>
|
||||
<app-hero-list></app-hero-list>
|
||||
<app-sales-tax></app-sales-tax>
|
||||
`
|
||||
`,
|
||||
imports: [HeroListComponent, SalesTaxComponent]
|
||||
})
|
||||
export class AppComponent { }
|
||||
|
||||
@@ -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
|
||||
@@ -9,7 +9,7 @@ const HEROES = [
|
||||
new Hero('Magneta', 'Manipulates metallic objects')
|
||||
];
|
||||
|
||||
@Injectable()
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class BackendService {
|
||||
constructor(private logger: Logger) {}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
@Injectable({providedIn: 'root'})
|
||||
// #docregion class
|
||||
export class Logger {
|
||||
log(msg: any) { console.log(msg); }
|
||||
|
||||
@@ -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';
|
||||
|
||||
|
||||
@@ -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: `
|
||||
<h2>Sales Tax Calculator</h2>
|
||||
@@ -15,7 +16,7 @@ import { TaxRateService } from './tax-rate.service';
|
||||
{{ getTax(amountBox.value) | currency:'USD':true:'1.2-2' }}</p>
|
||||
</div>
|
||||
`,
|
||||
providers: [SalesTaxService, TaxRateService]
|
||||
imports: [NgIf, CurrencyPipe]
|
||||
})
|
||||
export class SalesTaxComponent {
|
||||
constructor(private salesTaxService: SalesTaxService) { }
|
||||
|
||||
@@ -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) { }
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { Injectable } from '@angular/core';
|
||||
|
||||
@Injectable()
|
||||
@Injectable({providedIn: 'root'})
|
||||
export class TaxRateService {
|
||||
getRate(rateName: string) { return 0.10; } // 10% everywhere
|
||||
}
|
||||
|
||||
@@ -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
|
||||
]
|
||||
});
|
||||
|
||||
@@ -1,6 +0,0 @@
|
||||
|
||||
<select>
|
||||
<!--#docregion two-way-template-deprecated-->
|
||||
<option *ngFor="let optionName of options" [(value)]="optionName"></option>
|
||||
<!--#enddocregion two-way-template-deprecated-->
|
||||
</select>
|
||||
@@ -1,17 +1,5 @@
|
||||
<h1>Deprecation</h1>
|
||||
|
||||
<!--#docregion deprecated-example-->
|
||||
|
||||
<input [formControl]="control" [(ngModel)]="value">
|
||||
|
||||
<!--#enddocregion deprecated-example-->
|
||||
|
||||
<!--#docregion reactive-form-example-->
|
||||
|
||||
<input [formControl]="control">
|
||||
|
||||
<!--#enddocregion reactive-form-example-->
|
||||
|
||||
<!--#docregion template-driven-form-example-->
|
||||
|
||||
<input [(ngModel)]="value">
|
||||
|
||||
@@ -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
|
||||
});
|
||||
@@ -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<any>;
|
||||
// #enddocregion template-with-input-deprecated
|
||||
*/
|
||||
|
||||
// #docregion template-with-input
|
||||
@Input() tpl !: TemplateRef<any>;
|
||||
@ContentChild(TemplateRef) inlineTemplate !: TemplateRef<any>;
|
||||
// #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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
],
|
||||
};
|
||||
@@ -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')
|
||||
}];
|
||||
@@ -1 +0,0 @@
|
||||
<p>lazy works!</p>
|
||||
@@ -1,25 +0,0 @@
|
||||
import { ComponentFixture, TestBed } from '@angular/core/testing';
|
||||
|
||||
import { LazyComponent } from './lazy.component';
|
||||
|
||||
describe('LazyComponent', () => {
|
||||
let component: LazyComponent;
|
||||
let fixture: ComponentFixture<LazyComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ LazyComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(LazyComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -1,8 +1,8 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'app-lazy',
|
||||
templateUrl: './lazy.component.html',
|
||||
styleUrls: ['./lazy.component.css']
|
||||
template: `<p>lazy works!</p>`
|
||||
})
|
||||
export class LazyComponent {}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
import { Route } from '@angular/router';
|
||||
import { LazyComponent } from './lazy.component';
|
||||
|
||||
export default [
|
||||
{ path: '*', component: LazyComponent },
|
||||
// ... more child routes ...
|
||||
] as Route[];
|
||||
+6
-7
@@ -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: `<p>submit-button works!</p> `
|
||||
// #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: `<p>submit-button works!</p>`
|
||||
})
|
||||
export class SubmitButtonValidComponent {
|
||||
|
||||
-1
@@ -1 +0,0 @@
|
||||
<p>submit-button works!</p>
|
||||
-25
@@ -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<SubmitButtonComponent>;
|
||||
|
||||
beforeEach(async () => {
|
||||
await TestBed.configureTestingModule({
|
||||
declarations: [ SubmitButtonComponent ]
|
||||
})
|
||||
.compileComponents();
|
||||
});
|
||||
|
||||
beforeEach(() => {
|
||||
fixture = TestBed.createComponent(SubmitButtonComponent);
|
||||
component = fixture.componentInstance;
|
||||
fixture.detectChanges();
|
||||
});
|
||||
|
||||
it('should create', () => {
|
||||
expect(component).toBeTruthy();
|
||||
});
|
||||
});
|
||||
@@ -0,0 +1,17 @@
|
||||
<!--#docregion deprecated-example-->
|
||||
|
||||
<input [formControl]="control" [(ngModel)]="value">
|
||||
|
||||
<!--#enddocregion deprecated-example-->
|
||||
|
||||
<!--#docregion reactive-form-example-->
|
||||
|
||||
<input [formControl]="control">
|
||||
|
||||
<!--#enddocregion reactive-form-example-->
|
||||
|
||||
<select>
|
||||
<!--#docregion two-way-template-deprecated-->
|
||||
<option *ngFor="let optionName of options" [(value)]="optionName"></option>
|
||||
<!--#enddocregion two-way-template-deprecated-->
|
||||
</select>
|
||||
@@ -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<any>;
|
||||
// #enddocregion template-with-input-deprecated
|
||||
*/
|
||||
|
||||
@Input() tpl !: TemplateRef<any>;
|
||||
@ContentChild(TemplateRef) inlineTemplate !: TemplateRef<any>;
|
||||
|
||||
ngOnInit() {
|
||||
// #docregion deprecated-example
|
||||
|
||||
this.value = 'some value';
|
||||
|
||||
// #enddocregion deprecated-example
|
||||
this.setValue();
|
||||
}
|
||||
|
||||
setValue(): void {
|
||||
this.control.setValue('some value');
|
||||
}
|
||||
}
|
||||
+19
-2
@@ -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: [
|
||||
@@ -0,0 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-lazy',
|
||||
template: `<p>lazy works!</p>`
|
||||
})
|
||||
export class LazyComponent {}
|
||||
-1
@@ -4,7 +4,6 @@ import { CommonModule } from '@angular/common';
|
||||
import { LazyRoutingModule } from './lazy-routing.module';
|
||||
import { LazyComponent } from './lazy.component';
|
||||
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
LazyComponent
|
||||
@@ -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.
|
||||
@@ -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);
|
||||
|
||||
@@ -1,7 +0,0 @@
|
||||
load("//aio/content/examples:examples.bzl", "docs_example")
|
||||
|
||||
package(default_visibility = ["//visibility:public"])
|
||||
|
||||
docs_example(
|
||||
name = "displaying-data",
|
||||
)
|
||||
@@ -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!');
|
||||
});
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<h1>{{title}} [Ctor version]</h1>
|
||||
<h2>My favorite hero is: {{myHero}}</h2>
|
||||
`
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'Tour of Heroes';
|
||||
myHero = 'Windstorm';
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<h1>{{title}}</h1>
|
||||
<h2>My favorite hero is: {{myHero}}</h2>
|
||||
`
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'Tour of Heroes';
|
||||
myHero = 'Windstorm';
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<h1>{{title}}</h1>
|
||||
<h2>My favorite hero is: {{myHero}}</h2>
|
||||
<p>Heroes:</p>
|
||||
<ul>
|
||||
<li *ngFor="let hero of heroes">
|
||||
{{ hero }}
|
||||
</li>
|
||||
</ul>
|
||||
`
|
||||
})
|
||||
export class AppComponent {
|
||||
title = 'Tour of Heroes';
|
||||
heroes = ['Windstorm', 'Bombasto', 'Magneta', 'Tornado'];
|
||||
myHero = this.heroes[0];
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { Hero } from './hero';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<h1>{{title}}</h1>
|
||||
<h2>My favorite hero is: {{myHero.name}}</h2>
|
||||
<p>Heroes:</p>
|
||||
<ul>
|
||||
<li *ngFor="let hero of heroes">
|
||||
{{ hero.name }}
|
||||
</li>
|
||||
</ul>
|
||||
`
|
||||
})
|
||||
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];
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
import { Hero } from './hero';
|
||||
|
||||
@Component({
|
||||
selector: 'app-root',
|
||||
template: `
|
||||
<h1>{{title}}</h1>
|
||||
<h2>My favorite hero is: {{myHero.name}}</h2>
|
||||
<p>Heroes:</p>
|
||||
<ul>
|
||||
<li *ngFor="let hero of heroes">
|
||||
{{ hero.name }}
|
||||
</li>
|
||||
</ul>
|
||||
<p *ngIf="heroes.length > 3">There are many heroes!</p>
|
||||
`
|
||||
})
|
||||
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];
|
||||
}
|
||||
@@ -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 { }
|
||||
@@ -1,5 +0,0 @@
|
||||
export class Hero {
|
||||
constructor(
|
||||
public id: number,
|
||||
public name: string) { }
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>Displaying Data</title>
|
||||
<base href="/">
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<app-root></app-root>
|
||||
</body>
|
||||
</html>
|
||||
@@ -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));
|
||||
@@ -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"]
|
||||
}
|
||||
@@ -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},
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
<!-- #docplaster -->
|
||||
<!-- #docregion -->
|
||||
<h1><ng-container></h1>
|
||||
|
||||
<div *ngIf="hero">{{hero.name}}</div>
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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 { }
|
||||
@@ -1,6 +1,7 @@
|
||||
import { Component } from '@angular/core';
|
||||
|
||||
@Component({
|
||||
standalone: true,
|
||||
selector: 'content-comp',
|
||||
template:
|
||||
`<div>
|
||||
|
||||
@@ -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}}'
|
||||
})
|
||||
|
||||
@@ -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
|
||||
]
|
||||
});
|
||||
|
||||
@@ -42,7 +42,7 @@ The following are some of the key AngularJS built-in directives and their equiva
|
||||
|
||||
| AngularJS | Angular |
|
||||
|:--- |:--- |
|
||||
| <header><code>ng-app</code></header> <code-example hideCopy format="html" language="html"> <body ng-app="movieHunter"> </code-example> The application startup process is called **bootstrapping**. <br /> 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. | <header>Bootstrapping</header> <code-example header="main.ts" format="typescript" hideCopy language="typescript" path="ajs-quick-reference/src/main.ts"></code-example> <code-example hideCopy path="ajs-quick-reference/src/app/app.module.1.ts" header="app.module.ts"></code-example> 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`. |
|
||||
| <header><code>ng-app</code></header> <code-example hideCopy format="html" language="html"> <body ng-app="movieHunter"> </code-example> The application startup process is called **bootstrapping**. <br /> 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. | <header>Bootstrapping</header> <code-example header="main.ts" format="typescript" hideCopy language="typescript" path="ajs-quick-reference/src/main.ts">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].
|
||||
|:--- |:--- |
|
||||
| <header><code>orderBy</code></header> <code-example hideCopy format="html" language="html"> <tr ng-repeat="movie in movieList | orderBy : 'title'"> </code-example> Displays the collection in the order specified by the expression. In this example, the movie title orders the `movieList`. | <header>none</header> 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 |
|
||||
|:--- |:--- |
|
||||
| <header>IIFE</header> <code-example hideCopy format="typescript" language="typescript"> ( 
 function () { 
 … 
 }() 
); </code-example> In AngularJS, an IIFE around controller code keeps it out of the global namespace. | <header>none</header> This is a nonissue in Angular because ES 2015 modules handle the namespace for you. <br /> For more information on modules, see the [Modules][AioGuideArchitectureModules] section of the [Architecture Overview][AioGuideArchitecture]. |
|
||||
| <header>IIFE</header> <code-example hideCopy format="typescript" language="typescript"> ( 
 function () { 
 … 
 }() 
); </code-example> In AngularJS, an IIFE around controller code keeps it out of the global namespace. | <header>none</header> This is a nonissue in Angular because ES 2015 modules handle the namespace for you. |
|
||||
|
||||
### Angular modules → `NgModules`
|
||||
|
||||
| AngularJS | Angular |
|
||||
|:--- |:--- |
|
||||
| <header>Angular modules</header> <code-example hideCopy format="typescript" language="typescript"> angular .module( 
 "movieHunter", 
 [ 
 "ngRoute" 
 ] 
); </code-example> 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. | <header><code>NgModules</code></header> <code-example hideCopy path="ajs-quick-reference/src/app/app.module.1.ts"></code-example> NgModules, defined with the `NgModule` decorator, serve the same purpose: <ul> <li>`imports`: specifies the list of other modules that this module depends upon</li> <li>`declaration`: keeps track of your components, pipes, and directives.</li> </ul> For more information on modules, see [NgModules][AioGuideNgmodules]. |
|
||||
|
||||
### Controller registration → component decorator
|
||||
|
||||
| AngularJS | Angular |
|
||||
|:--- |:--- |
|
||||
| <header>Controller registration</header> <code-example hideCopy format="typescript" language="typescript"> angular .module( 
 "movieHunter" 
) .controller( 
 "MovieListCtrl", 
 [ 
 "movieService", 
 MovieListCtrl 
 ] 
); </code-example> AngularJS has code in each controller that looks up an appropriate Angular module and registers the controller with that module. <br /> 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. | <header>Component decorator</header> <code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="component"></code-example> 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. <br /> This is how you associate a template with logic, which is defined in the component class. <br /> For more information, see the [Components][AioGuideArchitectureComponents] section of the [Architecture Overview][AioGuideArchitecture] page. |
|
||||
| <header>Controller registration</header> <code-example hideCopy format="typescript" language="typescript"> angular .module( 
 "movieHunter" 
) .controller( 
 "MovieListCtrl", 
 [ 
 "movieService", 
 MovieListCtrl 
 ] 
); </code-example> AngularJS has code in each controller that looks up an appropriate AngularJS module and registers the controller with that module. <br /> 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. | <header>Component decorator</header> <code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="component"></code-example> 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. <br /> This is how you associate a template with logic, which is defined in the component class. <br /> For more information, see the [Components][AioGuideArchitectureComponents] section of the [Architecture Overview][AioGuideArchitecture] page. |
|
||||
|
||||
### Controller function → component class
|
||||
|
||||
| AngularJS | Angular |
|
||||
|:--- |:--- |
|
||||
| <header>Controller function</header> <code-example hideCopy format="typescript" language="typescript"> function MovieListCtrl(movieService) { 
 } </code-example> In AngularJS, you write the code for the model and methods in a controller function. | <header>Component class</header> <code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="class"></code-example> In Angular, you create a component class to contain the data model and control methods. Use the TypeScript <code>export</code> keyword to export the class so that the component can be imported into NgModules. <br /> For more information, see the [Components][AioGuideArchitectureComponents] section of the [Architecture Overview][AioGuideArchitecture] page. |
|
||||
| <header>Controller function</header> <code-example hideCopy format="typescript" language="typescript"> function MovieListCtrl(movieService) { 
 } </code-example> In AngularJS, you write the code for the model and methods in a controller function. | <header>Component class</header> <code-example hideCopy path="ajs-quick-reference/src/app/movie-list.component.ts" region="class"></code-example> In Angular, you create a component class to contain the data model and control methods. Use the TypeScript <code>export</code> keyword to export the class so that the component can be imported into other classes. <br /> 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.
|
||||
|
||||
<!-- end links -->
|
||||
|
||||
@reviewed 2023-08-14
|
||||
@reviewed 2023-09-25
|
||||
|
||||
@@ -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 `<app-hero-list></app-hero-list>`, 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
|
||||
|
||||
</div>
|
||||
|
||||
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
|
||||
|
||||
<!-- end links -->
|
||||
|
||||
@reviewed 2023-08-14
|
||||
@reviewed 2023-09-25
|
||||
|
||||
@@ -1,13 +1,20 @@
|
||||
# Introduction to modules
|
||||
|
||||
Angular applications are modular and Angular has its own modularity system called *NgModules*.
|
||||
|
||||
<div class="alert is-critical">
|
||||
|
||||
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).
|
||||
|
||||
</div>
|
||||
|
||||
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.
|
||||
|
||||
<code-example path="architecture/src/app/app.module.ts" region="imports"></code-example>
|
||||
<code-example path="architecture/src/app/mini-app.ts" region="imports"></code-example>
|
||||
|
||||
<code-example path="architecture/src/app/app.module.ts" region="export"></code-example>
|
||||
<code-example path="architecture/src/app/mini-app.ts" region="export"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
<!-- end links -->
|
||||
|
||||
@reviewed 2022-02-28
|
||||
@reviewed 2023-09-25
|
||||
|
||||
@@ -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.
|
||||
<code-example path="architecture/src/app/hero.service.ts" region="provide">
|
||||
</code-example>
|
||||
|
||||
* 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.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
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.
|
||||
|
||||
</div>
|
||||
|
||||
@@ -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.
|
||||
|
||||
<code-example format="typescript" language="typescript">
|
||||
|
||||
@Injectable({
|
||||
providedIn: 'root',
|
||||
})
|
||||
The tutorial uses this method to register the provider of `HeroService` class definition.
|
||||
|
||||
<code-example header="hero.service.ts (provide in root)" path="architecture/src/app/hero.service.ts" region="provide">
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example format="typescript" language="typescript">
|
||||
|
||||
@NgModule({
|
||||
providers: [
|
||||
BackendService,
|
||||
Logger
|
||||
],
|
||||
…
|
||||
})
|
||||
|
||||
</code-example>
|
||||
|
||||
* 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
|
||||
|
||||
<!-- end links -->
|
||||
|
||||
@reviewed 2022-02-28
|
||||
@reviewed 2023-09-25
|
||||
|
||||
@@ -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 <live-example></liv
|
||||
|
||||
</div>
|
||||
|
||||
## 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.
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
For a more detailed discussion, see [Introduction to modules](guide/architecture-modules).
|
||||
|
||||
</div>
|
||||
|
||||
## 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.
|
||||
|
||||
<div class="lightbox">
|
||||
|
||||
<img alt="overview" src="generated/images/guide/architecture/overview2.png">
|
||||
|
||||
</div>
|
||||
|
||||
* 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.
|
||||
|
||||
</div>
|
||||
|
||||
@@ -181,4 +146,4 @@ To learn about more tools and techniques that are available to help you build an
|
||||
|
||||
<!-- end links -->
|
||||
|
||||
@reviewed 2022-02-28
|
||||
@reviewed 2023-09-25
|
||||
|
||||
@@ -324,9 +324,9 @@ Support for using the `ngModel` input property and `ngModelChange` event with re
|
||||
|
||||
Now deprecated:
|
||||
|
||||
<code-example path="deprecation-guide/src/app/app.component.html" region="deprecated-example"></code-example>
|
||||
<code-example path="deprecation-guide/src/deprecated/app.component.html" region="deprecated-example"></code-example>
|
||||
|
||||
<code-example path="deprecation-guide/src/app/app.component.ts" region="deprecated-example"></code-example>
|
||||
<code-example path="deprecation-guide/src/deprecated/app.component.ts" region="deprecated-example"></code-example>
|
||||
|
||||
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\):
|
||||
|
||||
<code-example path="deprecation-guide/src/app/app.component.html" region="reactive-form-example"></code-example>
|
||||
<!-- Standalone Reactive Forms are not ready as of 2023-09-25; move example to deprecated -->
|
||||
<code-example path="deprecation-guide/src/deprecated/app.component.html" region="reactive-form-example"></code-example>
|
||||
|
||||
<code-example path="deprecation-guide/src/app/app.component.ts" region="reactive-form-example"></code-example>
|
||||
|
||||
**After** \(choice 2 - use template-driven forms\):
|
||||
**After** \(choice 2 - with template-driven forms\):
|
||||
|
||||
<code-example path="deprecation-guide/src/app/app.component.html" region="template-driven-form-example"></code-example>
|
||||
|
||||
@@ -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:
|
||||
|
||||
<code-example path="deprecation-guide/src/app/app.module.ts" region="reactive-form-no-warning"></code-example>
|
||||
<code-example path="deprecation-guide/src/deprecated/app.module.ts" region="reactive-form-no-warning"></code-example>
|
||||
|
||||
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.
|
||||
|
||||
<a id="router-can-load"></a>
|
||||
@@ -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.
|
||||
|
||||
<a id="loadChildren"></a>
|
||||
|
||||
### `loadChildren` string syntax (NgModule)
|
||||
|
||||
<div class="alert is-critical">
|
||||
|
||||
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).
|
||||
|
||||
</div>
|
||||
|
||||
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**:
|
||||
|
||||
<code-example path="deprecation-guide/src/deprecated/app.module.ts" language="typescript" region="lazyload-deprecated-syntax"></code-example>
|
||||
|
||||
**After**:
|
||||
|
||||
<code-example path="deprecation-guide/src/deprecated/app.module.ts" language="typescript" region="lazyload-syntax"></code-example>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
**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\).
|
||||
|
||||
</div>
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
**Declaration syntax**: <br />
|
||||
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`.
|
||||
|
||||
</div>
|
||||
|
||||
<a id="reflect-metadata"></a>
|
||||
|
||||
### 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:
|
||||
|
||||
<code-example path="deprecation-guide/src/app/app.component.ts" language="typescript" region="template-with-input-deprecated"></code-example>
|
||||
<code-example path="deprecation-guide/src/deprecated/app.component.ts" language="typescript" region="template-with-input-deprecated"></code-example>
|
||||
|
||||
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.
|
||||
|
||||
<code-example path="deprecation-guide/src/app/app.component.1.html" region="two-way-template-deprecated"></code-example>
|
||||
<code-example path="deprecation-guide/src/deprecated/app.component.html" region="two-way-template-deprecated"></code-example>
|
||||
|
||||
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**:
|
||||
|
||||
<code-example path="deprecation-guide/src/app/app.module.ts" language="typescript" region="ModuleWithProvidersNonGeneric"></code-example>
|
||||
<code-example path="deprecation-guide/src/deprecated/app.module.ts" language="typescript" region="ModuleWithProvidersNonGeneric"></code-example>
|
||||
|
||||
**After**:
|
||||
|
||||
<code-example path="deprecation-guide/src/app/app.module.ts" language="typescript" region="ModuleWithProvidersGeneric"></code-example>
|
||||
|
||||
<!--
|
||||
|
||||
### Internet Explorer 11
|
||||
|
||||
Angular support for Microsoft's Internet Explorer 11 \(IE11\) is deprecated and will be removed in Angular v13.
|
||||
Ending IE11 support allows Angular to take advantage of web platform APIs present only in evergreen browsers, resulting in better APIs for developers and more capabilities for application users.
|
||||
An additional motivation behind this removal is the drop in global usage of IE11 to just ~1% \(as of March 2021\).
|
||||
For full rationale and discussion behind this deprecation, see [RFC: Internet Explorer 11 support deprecation and removal](https://github.com/angular/angular/issues/41840).
|
||||
|
||||
<div class="alert is-helpful">
|
||||
|
||||
**NOTE**: <br />
|
||||
IE11 will be supported in Angular v12 LTS releases through November 2022.
|
||||
|
||||
</div>
|
||||
|
||||
-->
|
||||
<code-example path="deprecation-guide/src/deprecated/app.module.ts" language="typescript" region="ModuleWithProvidersGeneric"></code-example>
|
||||
|
||||
<a id="input-setter-coercion"></a>
|
||||
|
||||
@@ -575,11 +605,11 @@ This means that input coercion fields are no longer needed, as their effects can
|
||||
|
||||
For example, the following directive:
|
||||
|
||||
<code-example path="deprecation-guide/src/app/submit-button/submit-button.component.ts" language="typescript" region="submitButtonNarrow"></code-example>
|
||||
<code-example path="deprecation-guide/src/app/submit-button.component.ts" language="typescript" region="submitButtonNarrow"></code-example>
|
||||
|
||||
can be refactored as follows:
|
||||
|
||||
<code-example path="deprecation-guide/src/app/submit-button/submit-button.component.ts" language="typescript" region="submitButton"></code-example>
|
||||
<code-example path="deprecation-guide/src/app/submit-button.component.ts" language="typescript" region="submitButton"></code-example>
|
||||
|
||||
<a id="full-template-type-check"></a>
|
||||
|
||||
@@ -711,4 +741,4 @@ If you rely on the behavior that the same object instance should cause change de
|
||||
|
||||
<!-- end links -->
|
||||
|
||||
@reviewed 2023-05-03
|
||||
@reviewed 2023-09-26
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
<div class="callout is-helpful">
|
||||
|
||||
<header>String-based lazy loading</header>
|
||||
|
||||
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.
|
||||
|
||||
</div>
|
||||
|
||||
### Add another feature module
|
||||
|
||||
Use the same command to create a second lazy-loaded feature module with routing, along with its stub component.
|
||||
|
||||
@@ -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.
|
||||
|
||||
<code-example header="src/app/app.component.ts" path="displaying-data/src/app/app.component.1.ts"></code-example>
|
||||
<code-example format="html" language="html">
|
||||
|
||||
<label>My favorite hero is {{hero.name}}</label>
|
||||
|
||||
</code-example>
|
||||
|
||||
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.
|
||||
|
||||
<!-- end links -->
|
||||
|
||||
@reviewed 2022-02-28
|
||||
@reviewed 2023-09-26
|
||||
|
||||
@@ -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."
|
||||
}
|
||||
]
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user