diff --git a/aio/content/examples/styleguide/src/05-18/app/app.component.ts b/aio/content/examples/styleguide/src/05-18/app/app.component.ts new file mode 100644 index 0000000000..86728b8b80 --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/app.component.ts @@ -0,0 +1,7 @@ +import { Component } from '@angular/core'; + +@Component({ + selector: 'sg-app', + template: '' +}) +export class AppComponent { } diff --git a/aio/content/examples/styleguide/src/05-18/app/app.module.ts b/aio/content/examples/styleguide/src/05-18/app/app.module.ts new file mode 100644 index 0000000000..fe0b893ff2 --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/app.module.ts @@ -0,0 +1,20 @@ +import { NgModule } from '@angular/core'; +import { BrowserModule } from '@angular/platform-browser'; +import { RouterModule } from '@angular/router'; + +import { AppComponent } from './app.component'; +import { HeroComponent, HeroListComponent } from './heroes'; + +@NgModule({ + imports: [ + BrowserModule, + RouterModule.forChild([{ path: '05-18', component: AppComponent }]) + ], + declarations: [ + AppComponent, + HeroComponent, + HeroListComponent + ], + exports: [AppComponent] +}) +export class AppModule {} diff --git a/aio/content/examples/styleguide/src/05-18/app/heroes/hero-list/hero-list.component.ts b/aio/content/examples/styleguide/src/05-18/app/heroes/hero-list/hero-list.component.ts new file mode 100644 index 0000000000..5f82e7ec11 --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/heroes/hero-list/hero-list.component.ts @@ -0,0 +1,24 @@ +import { Component } from '@angular/core'; + +import { Hero } from '../shared/hero.model'; + +@Component({ + selector: 'toh-hero-list', + template: ` +
+ Our list of heroes: + + + Total powers: {{totalPowers}}
+ Average power: {{avgPower}} +
+ ` +}) +export class HeroListComponent { + heroes: Hero[] = []; + totalPowers = 1; + + get avgPower() { + return this.totalPowers / this.heroes.length; + } +} diff --git a/aio/content/examples/styleguide/src/05-18/app/heroes/hero-list/index.ts b/aio/content/examples/styleguide/src/05-18/app/heroes/hero-list/index.ts new file mode 100644 index 0000000000..c4bcb3278e --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/heroes/hero-list/index.ts @@ -0,0 +1 @@ +export * from './hero-list.component'; diff --git a/aio/content/examples/styleguide/src/05-18/app/heroes/hero/hero.component.avoid.ts b/aio/content/examples/styleguide/src/05-18/app/heroes/hero/hero.component.avoid.ts new file mode 100644 index 0000000000..6aa0a4edf4 --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/heroes/hero/hero.component.avoid.ts @@ -0,0 +1,15 @@ +import { Component, Input } from '@angular/core'; + +// #docregion example +@Component({ + selector: 'toh-hero', + template: `...` +}) +export class HeroComponent { + // The exclamation mark suppresses errors that a property is + // not initialized. + // Ignoring this enforcement can prevent the type checker + // from finding potential issues. + @Input() id!: string; +} +// #enddocregion example diff --git a/aio/content/examples/styleguide/src/05-18/app/heroes/hero/hero.component.optional.ts b/aio/content/examples/styleguide/src/05-18/app/heroes/hero/hero.component.optional.ts new file mode 100644 index 0000000000..f116c7d301 --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/heroes/hero/hero.component.optional.ts @@ -0,0 +1,17 @@ +import { Component, Input } from '@angular/core'; + +// #docregion example +@Component({ + selector: 'toh-hero', + template: `...` +}) +export class HeroComponent { + @Input() id?: string; + + process() { + if (this.id) { + // ... + } + } +} +// #enddocregion example diff --git a/aio/content/examples/styleguide/src/05-18/app/heroes/hero/hero.component.ts b/aio/content/examples/styleguide/src/05-18/app/heroes/hero/hero.component.ts new file mode 100644 index 0000000000..a8d5677fb4 --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/heroes/hero/hero.component.ts @@ -0,0 +1,11 @@ +import { Component, Input } from '@angular/core'; + +// #docregion example +@Component({ + selector: 'toh-hero', + template: `...` +}) +export class HeroComponent { + @Input() id = 'default_id'; +} +// #enddocregion example diff --git a/aio/content/examples/styleguide/src/05-18/app/heroes/hero/index.ts b/aio/content/examples/styleguide/src/05-18/app/heroes/hero/index.ts new file mode 100644 index 0000000000..084f36d703 --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/heroes/hero/index.ts @@ -0,0 +1 @@ +export * from './hero.component'; diff --git a/aio/content/examples/styleguide/src/05-18/app/heroes/index.ts b/aio/content/examples/styleguide/src/05-18/app/heroes/index.ts new file mode 100644 index 0000000000..dcf3e79bd3 --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/heroes/index.ts @@ -0,0 +1,3 @@ +export * from './hero'; +export * from './hero-list'; +export * from './shared'; diff --git a/aio/content/examples/styleguide/src/05-18/app/heroes/shared/hero.model.ts b/aio/content/examples/styleguide/src/05-18/app/heroes/shared/hero.model.ts new file mode 100644 index 0000000000..a61b497759 --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/heroes/shared/hero.model.ts @@ -0,0 +1,4 @@ +export interface Hero { + id: number; + name: string; +} diff --git a/aio/content/examples/styleguide/src/05-18/app/heroes/shared/index.ts b/aio/content/examples/styleguide/src/05-18/app/heroes/shared/index.ts new file mode 100644 index 0000000000..0dceb684c4 --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/heroes/shared/index.ts @@ -0,0 +1 @@ +export * from './hero.model'; diff --git a/aio/content/examples/styleguide/src/05-18/app/index.ts b/aio/content/examples/styleguide/src/05-18/app/index.ts new file mode 100644 index 0000000000..fe8300f1dd --- /dev/null +++ b/aio/content/examples/styleguide/src/05-18/app/index.ts @@ -0,0 +1,2 @@ +export * from './heroes'; +export * from './app.component'; diff --git a/aio/content/guide/styleguide.md b/aio/content/guide/styleguide.md index 9064cfa7a7..5d8da7825c 100644 --- a/aio/content/guide/styleguide.md +++ b/aio/content/guide/styleguide.md @@ -3381,6 +3381,23 @@ helps instantly identify which members of the component serve which purpose. Back to top +### Initialize inputs + +#### Style 05-18 + +TypeScript's `--strictPropertyInitialization` compiler option ensures that a class initializes its properties during construction. When enabled, this option causes the TypeScript compiler to report an error if the class does not set a value to any property that is not explicitly marked as optional. + +By design, Angular treats all `@Input` properties as optional. When possible, you should satisfy `--strictPropertyInitialization` by providing a default value. + + + +If the property is hard to construct a default value for, use `?` to explicitly mark the property as optional. + + + +You may want to have a required `@Input` field, meaning all your component users are required to pass that attribute. In such cases, use a default value. Just suppressing the TypeScript error with `!` is insufficient and should be avoided because it will prevent the type checker ensure the input value is provided. + + ## Directives