Skip to content

Commit

Permalink
docs: add a style recommendation for initializing inputs (angular#40698)
Browse files Browse the repository at this point in the history
This practice is to better align with `strictPropertyInitialization`
which is coming by default with strict mode in v12.

PR Close angular#40698
  • Loading branch information
mgechev authored and josephperrott committed Feb 13, 2021
1 parent 980f6a4 commit 72a00dc
Show file tree
Hide file tree
Showing 13 changed files with 123 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { Component } from '@angular/core';

@Component({
selector: 'sg-app',
template: '<toh-hero-list></toh-hero-list>'
})
export class AppComponent { }
20 changes: 20 additions & 0 deletions aio/content/examples/styleguide/src/05-18/app/app.module.ts
Original file line number Diff line number Diff line change
@@ -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 {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { Component } from '@angular/core';

import { Hero } from '../shared/hero.model';

@Component({
selector: 'toh-hero-list',
template: `
<section>
Our list of heroes:
<toh-hero *ngFor="let hero of heroes">
</toh-hero>
Total powers: {{totalPowers}}<br>
Average power: {{avgPower}}
</section>
`
})
export class HeroListComponent {
heroes: Hero[] = [];
totalPowers = 1;

get avgPower() {
return this.totalPowers / this.heroes.length;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './hero-list.component';
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -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
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './hero.component';
3 changes: 3 additions & 0 deletions aio/content/examples/styleguide/src/05-18/app/heroes/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
export * from './hero';
export * from './hero-list';
export * from './shared';
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
export interface Hero {
id: number;
name: string;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './hero.model';
2 changes: 2 additions & 0 deletions aio/content/examples/styleguide/src/05-18/app/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './heroes';
export * from './app.component';
17 changes: 17 additions & 0 deletions aio/content/guide/styleguide.md
Original file line number Diff line number Diff line change
Expand Up @@ -3381,6 +3381,23 @@ helps instantly identify which members of the component serve which purpose.

<a href="#toc">Back to top</a>

### 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.

<code-example path="styleguide/src/05-18/app/heroes/hero/hero.component.ts" region="example" header="app/heroes/hero/hero.component.ts"></code-example>

If the property is hard to construct a default value for, use `?` to explicitly mark the property as optional.

<code-example path="styleguide/src/05-18/app/heroes/hero/hero.component.optional.ts" region="example" header="app/heroes/hero/hero.component.ts"></code-example>

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.

<code-example path="styleguide/src/05-18/app/heroes/hero/hero.component.avoid.ts" region="example" header="app/heroes/hero/hero.component.ts"></code-example>

## Directives

Expand Down

0 comments on commit 72a00dc

Please sign in to comment.