docs: make all examples compatible with strict mode (#41999)

Turns on the `strict` compiler flag and resolves the compilation errors in the various AIO examples.

PR Close #41999
This commit is contained in:
Kristiyan Kostadinov 2021-05-08 16:02:03 +02:00 committed by atscott
parent 5960d4c513
commit e86a1d3441
244 changed files with 615 additions and 621 deletions

View File

@ -89,7 +89,7 @@ describe('AngularJS to Angular Quick Reference Tests', () => {
return element.all(by.css('app-movie-list tbody > tr')); return element.all(by.css('app-movie-list tbody > tr'));
} }
async function testFavoriteHero(heroName: string, expectedLabel: string) { async function testFavoriteHero(heroName: string | null, expectedLabel: string) {
const movieListComp = element(by.tagName('app-movie-list')); const movieListComp = element(by.tagName('app-movie-list'));
const heroInput = movieListComp.element(by.tagName('input')); const heroInput = movieListComp.element(by.tagName('input'));
const favoriteHeroLabel = movieListComp.element(by.tagName('h3')); const favoriteHeroLabel = movieListComp.element(by.tagName('h3'));

View File

@ -16,7 +16,7 @@ export class AppComponent {
eventType = '<not clicked yet>'; eventType = '<not clicked yet>';
isActive = true; isActive = true;
isImportant = true; isImportant = true;
movie: IMovie = null; movie: IMovie;
movies: IMovie[] = []; movies: IMovie[] = [];
showImage = true; showImage = true;
title = 'AngularJS to Angular Quick Ref Cookbook'; title = 'AngularJS to Angular Quick Ref Cookbook';

View File

@ -1,4 +1,3 @@
/* tslint:disable:no-unused-variable */
// #docplaster // #docplaster
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { IMovie } from './movie'; import { IMovie } from './movie';
@ -16,7 +15,7 @@ import { MovieService } from './movie.service';
// #docregion class // #docregion class
export class MovieListComponent { export class MovieListComponent {
// #enddocregion class // #enddocregion class
favoriteHero: string; favoriteHero: string | undefined;
showImage = false; showImage = false;
movies: IMovie[]; movies: IMovie[];

View File

@ -31,7 +31,7 @@ import { Hero } from './hero';
// #enddocregion auto-calc // #enddocregion auto-calc
}) })
export class HeroListAutoComponent { export class HeroListAutoComponent {
@Input() heroes: Hero[]; @Input() heroes: Hero[] = [];
@Output() remove = new EventEmitter<number>(); @Output() remove = new EventEmitter<number>();

View File

@ -44,7 +44,7 @@ import { Hero } from './hero';
// #enddocregion animationdef // #enddocregion animationdef
}) })
export class HeroListEnterLeaveComponent { export class HeroListEnterLeaveComponent {
@Input() heroes: Hero[]; @Input() heroes: Hero[] = [];
@Output() remove = new EventEmitter<number>(); @Output() remove = new EventEmitter<number>();

View File

@ -64,7 +64,7 @@ import { Hero } from './hero';
// #enddocregion animationdef // #enddocregion animationdef
}) })
export class HeroListGroupsComponent { export class HeroListGroupsComponent {
@Input() heroes: Hero[]; @Input() heroes: Hero[] = [];
@Output() remove = new EventEmitter<number>(); @Output() remove = new EventEmitter<number>();

View File

@ -4,6 +4,7 @@
import { Component, HostBinding, OnInit } from '@angular/core'; import { Component, HostBinding, OnInit } from '@angular/core';
import { trigger, transition, animate, style, query, stagger } from '@angular/animations'; import { trigger, transition, animate, style, query, stagger } from '@angular/animations';
import { HEROES } from './mock-heroes'; import { HEROES } from './mock-heroes';
import { Hero } from './hero';
// #docregion filter-animations // #docregion filter-animations
@Component({ @Component({
@ -58,7 +59,7 @@ export class HeroListPageComponent implements OnInit {
heroTotal = -1; heroTotal = -1;
// #enddocregion filter-animations // #enddocregion filter-animations
get heroes() { return this._heroes; } get heroes() { return this._heroes; }
private _heroes = []; private _heroes: Hero[] = [];
ngOnInit() { ngOnInit() {
this._heroes = HEROES; this._heroes = HEROES;

View File

@ -7,5 +7,5 @@ import { Hero } from './hero';
templateUrl: './hero-detail.component.html' templateUrl: './hero-detail.component.html'
}) })
export class HeroDetailComponent { export class HeroDetailComponent {
@Input() hero: Hero; @Input() hero!: Hero;
} }

View File

@ -13,8 +13,8 @@ import { HeroService } from './hero.service';
// #docregion class // #docregion class
export class HeroListComponent implements OnInit { export class HeroListComponent implements OnInit {
// #enddocregion metadata // #enddocregion metadata
heroes: Hero[]; heroes: Hero[] = [];
selectedHero: Hero; selectedHero: Hero | undefined;
// #docregion ctor // #docregion ctor
constructor(private service: HeroService) { } constructor(private service: HeroService) { }

View File

@ -7,5 +7,5 @@ import { Component } from '@angular/core';
}) })
// #docregion class // #docregion class
export class AppComponent { export class AppComponent {
color: string; color = '';
} }

View File

@ -19,7 +19,7 @@ export class HighlightDirective {
} }
@HostListener('mouseleave') onMouseLeave() { @HostListener('mouseleave') onMouseLeave() {
this.highlight(null); this.highlight('');
} }
private highlight(color: string) { private highlight(color: string) {

View File

@ -11,7 +11,7 @@ export class HighlightDirective {
constructor(private el: ElementRef) { } constructor(private el: ElementRef) { }
// #docregion input // #docregion input
@Input() appHighlight: string; @Input() appHighlight = '';
// #enddocregion input // #enddocregion input
@HostListener('mouseenter') onMouseEnter() { @HostListener('mouseenter') onMouseEnter() {
@ -19,7 +19,7 @@ export class HighlightDirective {
} }
@HostListener('mouseleave') onMouseLeave() { @HostListener('mouseleave') onMouseLeave() {
this.highlight(null); this.highlight('');
} }
private highlight(color: string) { private highlight(color: string) {

View File

@ -9,10 +9,10 @@ export class HighlightDirective {
constructor(private el: ElementRef) { } constructor(private el: ElementRef) { }
// #docregion defaultColor // #docregion defaultColor
@Input() defaultColor: string; @Input() defaultColor = '';
// #enddocregion defaultColor // #enddocregion defaultColor
@Input('appHighlight') highlightColor: string; @Input('appHighlight') highlightColor = '';
// #docregion mouse-enter // #docregion mouse-enter
@HostListener('mouseenter') onMouseEnter() { @HostListener('mouseenter') onMouseEnter() {
@ -21,7 +21,7 @@ export class HighlightDirective {
// #enddocregion mouse-enter // #enddocregion mouse-enter
@HostListener('mouseleave') onMouseLeave() { @HostListener('mouseleave') onMouseLeave() {
this.highlight(null); this.highlight('');
} }
private highlight(color: string) { private highlight(color: string) {

View File

@ -7,7 +7,7 @@ describe('Binding syntax e2e tests', () => {
// helper function used to test what's logged to the console // helper function used to test what's logged to the console
async function logChecker(contents) { async function logChecker(contents: string) {
const logs = await browser.manage().logs().get(logging.Type.BROWSER); const logs = await browser.manage().logs().get(logging.Type.BROWSER);
const messages = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false); const messages = logs.filter(({ message }) => message.indexOf(contents) !== -1 ? true : false);
expect(messages.length).toBeGreaterThan(0); expect(messages.length).toBeGreaterThan(0);

View File

@ -8,7 +8,7 @@ import { Component, ViewChild, ElementRef } from '@angular/core';
}) })
export class AppComponent { export class AppComponent {
@ViewChild('bindingInput') bindingInput: ElementRef; @ViewChild('bindingInput') bindingInput!: ElementRef;
isUnchanged = true; isUnchanged = true;

View File

@ -8,7 +8,7 @@
<p>Current item name: {{currentItem.name}}</p> <p>Current item name: {{currentItem.name}}</p>
<p> <p>
<label for="without">without NgModel:</label> <label for="without">without NgModel:</label>
<input [value]="currentItem.name" (input)="currentItem.name=getValue($event.target)" id="without"> <input [value]="currentItem.name" (input)="currentItem.name=getValue($event)" id="without">
</p> </p>
<p> <p>

View File

@ -13,16 +13,16 @@ export class AppComponent implements OnInit {
isUnchanged = true; isUnchanged = true;
isActive = true; isActive = true;
nullCustomer = null; nullCustomer: string | null = null;
currentCustomer = { currentCustomer = {
name: 'Laura' name: 'Laura'
}; };
item: Item; // defined to demonstrate template context precedence item!: Item; // defined to demonstrate template context precedence
items: Item[]; items: Item[] = [];
// #docregion item // #docregion item
currentItem: Item; currentItem!: Item;
// #enddocregion item // #enddocregion item
@ -34,11 +34,11 @@ export class AppComponent implements OnInit {
itemIdIncrement = 1; itemIdIncrement = 1;
// #docregion setClasses // #docregion setClasses
currentClasses: {}; currentClasses: Record<string, boolean> = {};
// #enddocregion setClasses // #enddocregion setClasses
// #docregion setStyles // #docregion setStyles
currentStyles: {}; currentStyles: Record<string, string> = {};
// #enddocregion setStyles // #enddocregion setStyles
ngOnInit() { ngOnInit() {
@ -114,8 +114,8 @@ export class AppComponent implements OnInit {
trackById(index: number, item: any): number { return item.id; } trackById(index: number, item: any): number { return item.id; }
getValue(target: EventTarget): string { getValue(event: Event): string {
return (target as HTMLInputElement).value; return (event.target as HTMLInputElement).value;
} }
} }

View File

@ -10,7 +10,7 @@ import { Item } from '../item';
export class ItemDetailComponent { export class ItemDetailComponent {
@Input() item: Item; @Input() item!: Item;
constructor() { } constructor() { }

View File

@ -8,7 +8,7 @@ import { Item } from './item';
// #docregion input // #docregion input
export class StoutItemComponent { export class StoutItemComponent {
@Input() item: Item; @Input() item!: Item;
} }
// #enddocregion input // #enddocregion input
@ -18,7 +18,7 @@ export class StoutItemComponent {
template: `This is the brightest {{item.name}} in town.` template: `This is the brightest {{item.name}} in town.`
}) })
export class BestItemComponent { export class BestItemComponent {
@Input() item: Item; @Input() item!: Item;
} }
@Component({ @Component({
@ -26,7 +26,7 @@ export class BestItemComponent {
template: `Which is the slimmest {{item.name}}?` template: `Which is the slimmest {{item.name}}?`
}) })
export class DeviceItemComponent { export class DeviceItemComponent {
@Input() item: Item; @Input() item!: Item;
} }
@Component({ @Component({
@ -34,7 +34,7 @@ export class DeviceItemComponent {
template: `Has anyone seen my {{item.name}}?` template: `Has anyone seen my {{item.name}}?`
}) })
export class LostItemComponent { export class LostItemComponent {
@Input() item: Item; @Input() item!: Item;
} }
@Component({ @Component({
@ -42,7 +42,7 @@ export class LostItemComponent {
template: `{{message}}` template: `{{message}}`
}) })
export class UnknownItemComponent { export class UnknownItemComponent {
@Input() item: Item; @Input() item!: Item;
get message() { get message() {
return this.item && this.item.name ? return this.item && this.item.name ?
`${this.item.name} is strange and mysterious.` : `${this.item.name} is strange and mysterious.` :

View File

@ -3,7 +3,7 @@ export class Item {
static items: Item[] = [ static items: Item[] = [
new Item( new Item(
null, 0,
'Teapot', 'Teapot',
'stout' 'stout'
), ),
@ -15,7 +15,7 @@ export class Item {
constructor( constructor(
public id?: number, public id: number,
public name?: string, public name?: string,
public feature?: string, public feature?: string,
public url?: string, public url?: string,
@ -25,6 +25,6 @@ export class Item {
} }
clone(): Item { clone(): Item {
return Object.assign(new Item(), this); return Object.assign(new Item(this.id), this);
} }
} }

View File

@ -2,11 +2,11 @@ import { docRegionChain, docRegionObservable, docRegionUnsubscribe } from './obs
describe('observables', () => { describe('observables', () => {
it('should print 2', (doneFn: DoneFn) => { it('should print 2', (doneFn: DoneFn) => {
const consoleLogSpy = spyOn(console, 'log'); const consoleSpy = jasmine.createSpyObj<Console>('console', ['log']);
const observable = docRegionObservable(console); const observable = docRegionObservable(consoleSpy);
observable.subscribe(() => { observable.subscribe(() => {
expect(consoleLogSpy).toHaveBeenCalledTimes(1); expect(consoleSpy.log).toHaveBeenCalledTimes(1);
expect(consoleLogSpy).toHaveBeenCalledWith(2); expect(consoleSpy.log).toHaveBeenCalledWith(2);
doneFn(); doneFn();
}); });
}); });

View File

@ -2,11 +2,11 @@ import { docRegionError, docRegionPromise } from './promises';
describe('promises', () => { describe('promises', () => {
it('should print 2', (doneFn: DoneFn) => { it('should print 2', (doneFn: DoneFn) => {
const consoleLogSpy = spyOn(console, 'log'); const consoleSpy = jasmine.createSpyObj<Console>('console', ['log']);
const pr = docRegionPromise(console, 2); const pr = docRegionPromise(consoleSpy, 2);
pr.then((value) => { pr.then((value) => {
expect(consoleLogSpy).toHaveBeenCalledTimes(1); expect(consoleSpy.log).toHaveBeenCalledTimes(1);
expect(consoleLogSpy).toHaveBeenCalledWith(2); expect(consoleSpy.log).toHaveBeenCalledWith(2);
expect(value).toBe(4); expect(value).toBe(4);
doneFn(); doneFn();
}); });

View File

@ -3,7 +3,7 @@
export function docRegionPromise(console: Console, inputValue: number) { export function docRegionPromise(console: Console, inputValue: number) {
// #docregion promise // #docregion promise
// initiate execution // initiate execution
let promise = new Promise<number>((resolve, reject) => { let promise = new Promise<number>(resolve => {
// Executer fn... // Executer fn...
// #enddocregion promise // #enddocregion promise
// The below is used in the unit tests. // The below is used in the unit tests.

View File

@ -18,7 +18,7 @@ import { Subscription } from 'rxjs';
` `
}) })
export class AstronautComponent implements OnDestroy { export class AstronautComponent implements OnDestroy {
@Input() astronaut: string; @Input() astronaut = '';
mission = '<no mission announced>'; mission = '<no mission announced>';
confirmed = false; confirmed = false;
announced = false; announced = false;

View File

@ -40,7 +40,7 @@ export class CountdownLocalVarParentComponent { }
export class CountdownViewChildParentComponent implements AfterViewInit { export class CountdownViewChildParentComponent implements AfterViewInit {
@ViewChild(CountdownTimerComponent) @ViewChild(CountdownTimerComponent)
private timerComponent: CountdownTimerComponent; private timerComponent!: CountdownTimerComponent;
seconds() { return 0; } seconds() { return 0; }

View File

@ -11,7 +11,7 @@ import { Hero } from './hero';
` `
}) })
export class HeroChildComponent { export class HeroChildComponent {
@Input() hero: Hero; @Input() hero!: Hero;
@Input('master') masterName: string; // tslint:disable-line: no-input-rename @Input('master') masterName = ''; // tslint:disable-line: no-input-rename
} }
// #enddocregion // #enddocregion

View File

@ -13,8 +13,8 @@ import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
` `
}) })
export class VersionChildComponent implements OnChanges { export class VersionChildComponent implements OnChanges {
@Input() major: number; @Input() major = 0;
@Input() minor: number; @Input() minor = 0;
changeLog: string[] = []; changeLog: string[] = [];
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {

View File

@ -10,7 +10,7 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
` `
}) })
export class VoterComponent { export class VoterComponent {
@Input() name: string; @Input() name = '';
@Output() voted = new EventEmitter<boolean>(); @Output() voted = new EventEmitter<boolean>();
didVote = false; didVote = false;

View File

@ -12,5 +12,5 @@ import { Hero } from './hero';
` `
}) })
export class HeroAppMainComponent { export class HeroAppMainComponent {
@Input() hero: Hero; @Input() hero!: Hero;
} }

View File

@ -17,7 +17,7 @@ import { Hero } from './hero';
}) })
// #enddocregion inlinestyles // #enddocregion inlinestyles
export class HeroControlsComponent { export class HeroControlsComponent {
@Input() hero: Hero; @Input() hero!: Hero;
activate() { activate() {
this.hero.active = true; this.hero.active = true;

View File

@ -11,5 +11,5 @@ import { Hero } from './hero';
styleUrls: ['./hero-details.component.css'] styleUrls: ['./hero-details.component.css']
}) })
export class HeroDetailsComponent { export class HeroDetailsComponent {
@Input() hero: Hero; @Input() hero!: Hero;
} }

View File

@ -16,5 +16,5 @@ import { Hero } from './hero';
}) })
// #enddocregion stylelink // #enddocregion stylelink
export class HeroTeamComponent { export class HeroTeamComponent {
@Input() hero: Hero; @Input() hero!: Hero;
} }

View File

@ -1,5 +1,5 @@
export class Hero { export class Hero {
active: boolean; active = false;
constructor(public name: string, constructor(public name: string,
public team: string[]) { public team: string[]) {

View File

@ -37,6 +37,6 @@ export class ZippyComponent {
contentId = `zippy-${nextId++}`; contentId = `zippy-${nextId++}`;
@Input() expanded = false; @Input() expanded = false;
// #docregion contentchild // #docregion contentchild
@ContentChild(ZippyContentDirective) content: ZippyContentDirective; @ContentChild(ZippyContentDirective) content!: ZippyContentDirective;
// #enddocregion contentchild // #enddocregion contentchild
} }

View File

@ -1,4 +1,4 @@
import { browser, element, by } from 'protractor'; import { browser, element, by, ElementFinder } from 'protractor';
describe('Dependency Injection Cookbook', () => { describe('Dependency Injection Cookbook', () => {
@ -19,7 +19,7 @@ describe('Dependency Injection Cookbook', () => {
expect(await sortedHeroes.isPresent()).toBe(true); expect(await sortedHeroes.isPresent()).toBe(true);
const sortedHeroElems = element.all(by.css('app-sorted-heroes div')); const sortedHeroElems = element.all(by.css('app-sorted-heroes div'));
const sortedHeroNames = await sortedHeroElems.map(elem => elem.getText()); const sortedHeroNames = await sortedHeroElems.map(elem => elem?.getText());
expect(sortedHeroNames).toEqual(['Dr Nice', 'Magma', 'RubberMan']); expect(sortedHeroNames).toEqual(['Dr Nice', 'Magma', 'RubberMan']);
}); });

View File

@ -16,7 +16,7 @@ import { HeroCacheService } from './hero-cache.service';
}) })
export class HeroBioComponent implements OnInit { export class HeroBioComponent implements OnInit {
@Input() heroId: number; @Input() heroId = 0;
constructor(private heroCache: HeroCacheService) { } constructor(private heroCache: HeroCacheService) { }

View File

@ -7,7 +7,7 @@ import { HeroService } from './hero.service';
// #docregion service // #docregion service
@Injectable() @Injectable()
export class HeroCacheService { export class HeroCacheService {
hero: Hero; hero!: Hero;
constructor(private heroService: HeroService) {} constructor(private heroService: HeroService) {}
fetchCachedHero(id: number) { fetchCachedHero(id: number) {

View File

@ -15,7 +15,7 @@ export class HeroService {
]; ];
getHeroById(id: number): Hero { getHeroById(id: number): Hero {
return this.heroes.find(hero => hero.id === id); return this.heroes.find(hero => hero.id === id)!;
} }
getAllHeroes(): Array<Hero> { getAllHeroes(): Array<Hero> {

View File

@ -7,7 +7,7 @@ import { Directive, ElementRef, HostListener, Input } from '@angular/core';
}) })
export class HighlightDirective { export class HighlightDirective {
@Input('appHighlight') highlightColor: string; @Input('appHighlight') highlightColor = '';
private el: HTMLElement; private el: HTMLElement;
@ -20,7 +20,7 @@ export class HighlightDirective {
} }
@HostListener('mouseleave') onMouseLeave() { @HostListener('mouseleave') onMouseLeave() {
this.highlight(null); this.highlight('');
} }
private highlight(color: string) { private highlight(color: string) {

View File

@ -2,8 +2,8 @@
// Class used as a "narrowing" interface that exposes a minimal logger // Class used as a "narrowing" interface that exposes a minimal logger
// Other members of the actual implementation are invisible // Other members of the actual implementation are invisible
export abstract class MinimalLogger { export abstract class MinimalLogger {
logs: string[]; abstract logs: string[];
logInfo: (msg: string) => void; abstract logInfo: (msg: string) => void;
} }
// #enddocregion // #enddocregion

View File

@ -8,7 +8,7 @@ export abstract class Base { name = 'Count Basie'; }
// Marker class, used as an interface // Marker class, used as an interface
// #docregion parent // #docregion parent
export abstract class Parent { name: string; } export abstract class Parent { abstract name: string; }
// #enddocregion parent // #enddocregion parent
const DifferentParent = Parent; const DifferentParent = Parent;

View File

@ -15,7 +15,7 @@ import { HeroService } from './hero.service';
export class HeroesBaseComponent implements OnInit { export class HeroesBaseComponent implements OnInit {
constructor(private heroService: HeroService) { } constructor(private heroService: HeroService) { }
heroes: Array<Hero>; heroes: Hero[] = [];
ngOnInit() { ngOnInit() {
this.heroes = this.heroService.getAllHeroes(); this.heroes = this.heroService.getAllHeroes();

View File

@ -7,8 +7,8 @@ import { UserService } from './user.service';
providedIn: 'root' providedIn: 'root'
}) })
export class UserContextService { export class UserContextService {
name: string; name = '';
role: string; role = '';
loggedInSince: Date; loggedInSince: Date;
constructor(private userService: UserService, private loggerService: LoggerService) { constructor(private userService: UserService, private loggerService: LoggerService) {

View File

@ -1,6 +1,6 @@
// #docplaster // #docplaster
// #docregion // #docregion
import { Component, Injector, OnInit } from '@angular/core'; import { Component, Injector } from '@angular/core';
import { Car, Engine, Tires } from './car/car'; import { Car, Engine, Tires } from './car/car';
import { Hero } from './heroes/hero'; import { Hero } from './heroes/hero';
@ -18,7 +18,7 @@ import { Logger } from './logger.service';
`, `,
providers: [Car, Engine, Tires, heroServiceProvider, Logger] providers: [Car, Engine, Tires, heroServiceProvider, Logger]
}) })
export class InjectorComponent implements OnInit { export class InjectorComponent {
car: Car; car: Car;
// #docregion get-hero-service // #docregion get-hero-service
@ -26,9 +26,7 @@ export class InjectorComponent implements OnInit {
// #enddocregion get-hero-service // #enddocregion get-hero-service
hero: Hero; hero: Hero;
constructor(private injector: Injector) { } constructor(private injector: Injector) {
ngOnInit() {
this.car = this.injector.get(Car); this.car = this.injector.get(Car);
this.heroService = this.injector.get(HeroService); this.heroService = this.injector.get(HeroService);
this.hero = this.heroService.getHeroes()[0]; this.hero = this.heroService.getHeroes()[0];

View File

@ -210,7 +210,7 @@ export class Provider8Component {
// #enddocregion providers-9 // #enddocregion providers-9
}) })
export class Provider9Component implements OnInit { export class Provider9Component implements OnInit {
log: string; log = '';
/* /*
// #docregion provider-9-ctor-interface // #docregion provider-9-ctor-interface
// Can't inject using the interface as the parameter type // Can't inject using the interface as the parameter type
@ -237,7 +237,7 @@ const someMessage = 'Hello from the injected logger';
providers: [{ provide: Logger, useValue: null }] providers: [{ provide: Logger, useValue: null }]
}) })
export class Provider10Component implements OnInit { export class Provider10Component implements OnInit {
log: string; log = '';
constructor(@Optional() private logger?: Logger) { constructor(@Optional() private logger?: Logger) {
if (this.logger) { if (this.logger) {
this.logger.log(someMessage); this.logger.log(someMessage);

View File

@ -13,7 +13,7 @@ export class AppComponent {
// #enddocregion class-skeleton // #enddocregion class-skeleton
title = 'Authors Style Guide Sample'; title = 'Authors Style Guide Sample';
heroes = HEROES; heroes = HEROES;
selectedHero: Hero; selectedHero!: Hero;
onSelect(hero: Hero): void { onSelect(hero: Hero): void {
this.selectedHero = hero; this.selectedHero = hero;

View File

@ -18,9 +18,9 @@ import { AdComponent } from './ad.component';
}) })
// #docregion class // #docregion class
export class AdBannerComponent implements OnInit, OnDestroy { export class AdBannerComponent implements OnInit, OnDestroy {
@Input() ads: AdItem[]; @Input() ads: AdItem[] = [];
currentAdIndex = -1; currentAdIndex = -1;
@ViewChild(AdDirective, {static: true}) adHost: AdDirective; @ViewChild(AdDirective, {static: true}) adHost!: AdDirective;
interval: any; interval: any;
constructor(private componentFactoryResolver: ComponentFactoryResolver) { } constructor(private componentFactoryResolver: ComponentFactoryResolver) { }

View File

@ -13,7 +13,7 @@ import { AdItem } from './ad-item';
` `
}) })
export class AppComponent implements OnInit { export class AppComponent implements OnInit {
ads: AdItem[]; ads: AdItem[] = [];
constructor(private adService: AdService) {} constructor(private adService: AdService) {}

View File

@ -9,7 +9,7 @@ import { QuestionBase } from './question-base';
templateUrl: './dynamic-form-question.component.html' templateUrl: './dynamic-form-question.component.html'
}) })
export class DynamicFormQuestionComponent { export class DynamicFormQuestionComponent {
@Input() question: QuestionBase<string>; @Input() question!: QuestionBase<string>;
@Input() form: FormGroup; @Input() form!: FormGroup;
get isValid() { return this.form.controls[this.question.key].valid; } get isValid() { return this.form.controls[this.question.key].valid; }
} }

View File

@ -12,14 +12,14 @@ import { QuestionControlService } from './question-control.service';
}) })
export class DynamicFormComponent implements OnInit { export class DynamicFormComponent implements OnInit {
@Input() questions: QuestionBase<string>[] = []; @Input() questions: QuestionBase<string>[] | null = [];
form: FormGroup; form!: FormGroup;
payLoad = ''; payLoad = '';
constructor(private qcs: QuestionControlService) { } constructor(private qcs: QuestionControlService) {}
ngOnInit() { ngOnInit() {
this.form = this.qcs.toFormGroup(this.questions); this.form = this.qcs.toFormGroup(this.questions as QuestionBase<string>[]);
} }
onSubmit() { onSubmit() {

View File

@ -1,6 +1,6 @@
// #docregion // #docregion
export class QuestionBase<T> { export class QuestionBase<T> {
value: T; value: T|undefined;
key: string; key: string;
label: string; label: string;
required: boolean; required: boolean;

View File

@ -47,7 +47,7 @@ export class PopupComponent {
this._message = message; this._message = message;
this.state = 'opened'; this.state = 'opened';
} }
private _message: string; private _message = '';
@Output() @Output()
closed = new EventEmitter(); closed = new EventEmitter();

View File

@ -20,7 +20,7 @@
<!-- #docregion event-binding-3--> <!-- #docregion event-binding-3-->
<input [value]="currentItem.name" <input [value]="currentItem.name"
(input)="currentItem.name=getValue($event.target)"> (input)="currentItem.name=getValue($event)">
<!-- #enddocregion event-binding-3--> <!-- #enddocregion event-binding-3-->
without NgModel without NgModel
</div> </div>

View File

@ -27,8 +27,8 @@ export class AppComponent {
} }
// #docregion getValue // #docregion getValue
getValue(target: EventTarget): string { getValue(event: Event): string {
return (target as HTMLInputElement).value; return (event.target as HTMLInputElement).value;
} }
// #enddocregion getValue // #enddocregion getValue
} }

View File

@ -10,7 +10,7 @@ import { Item } from '../item';
}) })
export class ItemDetailComponent { export class ItemDetailComponent {
@Input() item; @Input() item!: Item;
itemImageUrl = 'assets/teapot.svg'; itemImageUrl = 'assets/teapot.svg';
lineThrough = ''; lineThrough = '';
displayNone = ''; displayNone = '';

View File

@ -1,4 +1,4 @@
export class Item { export class Item {
name: ''; name = '';
} }

View File

@ -18,13 +18,13 @@
<div *ngIf="name.invalid && (name.dirty || name.touched)" <div *ngIf="name.invalid && (name.dirty || name.touched)"
class="alert alert-danger"> class="alert alert-danger">
<div *ngIf="name.errors.required"> <div *ngIf="name.errors?.required">
Name is required. Name is required.
</div> </div>
<div *ngIf="name.errors.minlength"> <div *ngIf="name.errors?.minlength">
Name must be at least 4 characters long. Name must be at least 4 characters long.
</div> </div>
<div *ngIf="name.errors.forbiddenName"> <div *ngIf="name.errors?.forbiddenName">
Name cannot be Bob. Name cannot be Bob.
</div> </div>
</div> </div>
@ -59,7 +59,7 @@
</select> </select>
<div *ngIf="power.invalid && power.touched" class="alert alert-danger"> <div *ngIf="power.invalid && power.touched" class="alert alert-danger">
<div *ngIf="power.errors.required">Power is required.</div> <div *ngIf="power.errors?.required">Power is required.</div>
</div> </div>
</div> </div>

View File

@ -17,7 +17,7 @@ export class HeroFormReactiveComponent implements OnInit {
hero = { name: 'Dr.', alterEgo: 'Dr. What', power: this.powers[0] }; hero = { name: 'Dr.', alterEgo: 'Dr. What', power: this.powers[0] };
heroForm: FormGroup; heroForm!: FormGroup;
ngOnInit(): void { ngOnInit(): void {
this.heroForm = new FormGroup({ this.heroForm = new FormGroup({
@ -34,11 +34,11 @@ export class HeroFormReactiveComponent implements OnInit {
}, { validators: identityRevealedValidator }); // <-- add custom validator at the FormGroup level }, { validators: identityRevealedValidator }); // <-- add custom validator at the FormGroup level
} }
get name() { return this.heroForm.get('name'); } get name() { return this.heroForm.get('name')!; }
get power() { return this.heroForm.get('power'); } get power() { return this.heroForm.get('power')!; }
get alterEgo() { return this.heroForm.get('alterEgo'); } get alterEgo() { return this.heroForm.get('alterEgo')!; }
constructor(private alterEgoValidator: UniqueAlterEgoValidator) { } constructor(private alterEgoValidator: UniqueAlterEgoValidator) { }
} }

View File

@ -20,7 +20,7 @@ export function forbiddenNameValidator(nameRe: RegExp): ValidatorFn {
// #enddocregion directive-providers // #enddocregion directive-providers
}) })
export class ForbiddenValidatorDirective implements Validator { export class ForbiddenValidatorDirective implements Validator {
@Input('appForbiddenName') forbiddenName: string; @Input('appForbiddenName') forbiddenName = '';
validate(control: AbstractControl): ValidationErrors | null { validate(control: AbstractControl): ValidationErrors | null {
return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control) return this.forbiddenName ? forbiddenNameValidator(new RegExp(this.forbiddenName, 'i'))(control)

View File

@ -18,7 +18,7 @@ export const identityRevealedValidator: ValidatorFn = (control: AbstractControl)
providers: [{ provide: NG_VALIDATORS, useExisting: IdentityRevealedValidatorDirective, multi: true }] providers: [{ provide: NG_VALIDATORS, useExisting: IdentityRevealedValidatorDirective, multi: true }]
}) })
export class IdentityRevealedValidatorDirective implements Validator { export class IdentityRevealedValidatorDirective implements Validator {
validate(control: AbstractControl): ValidationErrors { validate(control: AbstractControl): ValidationErrors | null {
return identityRevealedValidator(control); return identityRevealedValidator(control);
} }
} }

View File

@ -19,13 +19,13 @@
<div *ngIf="name.invalid && (name.dirty || name.touched)" <div *ngIf="name.invalid && (name.dirty || name.touched)"
class="alert"> class="alert">
<div *ngIf="name.errors.required"> <div *ngIf="name.errors?.required">
Name is required. Name is required.
</div> </div>
<div *ngIf="name.errors.minlength"> <div *ngIf="name.errors?.minlength">
Name must be at least 4 characters long. Name must be at least 4 characters long.
</div> </div>
<div *ngIf="name.errors.forbiddenName"> <div *ngIf="name.errors?.forbiddenName">
Name cannot be Bob. Name cannot be Bob.
</div> </div>

View File

@ -65,7 +65,7 @@ describe('Getting Started', () => {
await pageElements.productListLinks.get(0).click(); await pageElements.productListLinks.get(0).click();
const product = pageElements.productDetailsPage; const product = pageElements.productDetailsPage;
const buyButton = await product.element(by.css('button')); const buyButton = product.element(by.css('button'));
const checkoutLink = pageElements.topBarCheckoutLink; const checkoutLink = pageElements.topBarCheckoutLink;
await buyButton.click(); await buyButton.click();
@ -89,12 +89,12 @@ describe('Getting Started', () => {
const checkoutLink = pageElements.topBarCheckoutLink; const checkoutLink = pageElements.topBarCheckoutLink;
const productDetailsPage = pageElements.productDetailsPage; const productDetailsPage = pageElements.productDetailsPage;
const buyButton = await productDetailsPage.element(by.css('button')); const buyButton = productDetailsPage.element(by.css('button'));
const cartPage = pageElements.cartPage; const cartPage = pageElements.cartPage;
const inputFields = cartPage.all(by.css('form input')); const inputFields = cartPage.all(by.css('form input'));
const purchaseButton = await cartPage.element(by.css('button')); const purchaseButton = cartPage.element(by.css('button'));
const nameField = inputFields.get(0); const nameField = inputFields.get(0);
const addressField = inputFields.get(1); const addressField = inputFields.get(1);

View File

@ -2,6 +2,7 @@
// #docregion import-http // #docregion import-http
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http'; import { HttpClient } from '@angular/common/http';
import { Product } from './products';
// #enddocregion import-http // #enddocregion import-http
@Injectable({ @Injectable({
@ -10,7 +11,7 @@ import { HttpClient } from '@angular/common/http';
// #docregion props, methods, inject-http, get-shipping // #docregion props, methods, inject-http, get-shipping
export class CartService { export class CartService {
// #enddocregion get-shipping // #enddocregion get-shipping
items = []; items: Product[] = [];
// #enddocregion props, methods // #enddocregion props, methods
constructor( constructor(
@ -19,7 +20,7 @@ export class CartService {
// #enddocregion inject-http // #enddocregion inject-http
// #docregion methods // #docregion methods
addToCart(product) { addToCart(product: Product) {
this.items.push(product); this.items.push(product);
} }

View File

@ -3,6 +3,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
// #enddocregion as-generated // #enddocregion as-generated
import { Input } from '@angular/core'; import { Input } from '@angular/core';
import { Product } from '../products';
// #enddocregion imports // #enddocregion imports
// #docregion as-generated // #docregion as-generated
@ -14,7 +15,7 @@ import { Input } from '@angular/core';
// #docregion input-decorator // #docregion input-decorator
export class ProductAlertsComponent implements OnInit { export class ProductAlertsComponent implements OnInit {
// #enddocregion as-generated // #enddocregion as-generated
@Input() product; @Input() product!: Product;
// #docregion as-generated // #docregion as-generated
constructor() { } constructor() { }

View File

@ -3,6 +3,7 @@
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { Input } from '@angular/core'; import { Input } from '@angular/core';
import { Output, EventEmitter } from '@angular/core'; import { Output, EventEmitter } from '@angular/core';
import { Product } from '../products';
// #enddocregion imports // #enddocregion imports
@Component({ @Component({
@ -12,6 +13,6 @@ import { Output, EventEmitter } from '@angular/core';
}) })
// #docregion input-output // #docregion input-output
export class ProductAlertsComponent { export class ProductAlertsComponent {
@Input() product; @Input() product!: Product;
@Output() notify = new EventEmitter(); @Output() notify = new EventEmitter();
} }

View File

@ -3,7 +3,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { products } from '../products'; import { Product, products } from '../products';
// #enddocregion imports // #enddocregion imports
@Component({ @Component({
@ -13,7 +13,7 @@ import { products } from '../products';
}) })
// #docregion props-methods, product-prop // #docregion props-methods, product-prop
export class ProductDetailsComponent implements OnInit { export class ProductDetailsComponent implements OnInit {
product; product: Product|undefined;
// #enddocregion product-prop // #enddocregion product-prop
constructor( constructor(

View File

@ -3,7 +3,7 @@
import { Component, OnInit } from '@angular/core'; import { Component, OnInit } from '@angular/core';
import { ActivatedRoute } from '@angular/router'; import { ActivatedRoute } from '@angular/router';
import { products } from '../products'; import { Product, products } from '../products';
import { CartService } from '../cart.service'; import { CartService } from '../cart.service';
// #enddocregion cart-service // #enddocregion cart-service
@ -15,7 +15,7 @@ import { CartService } from '../cart.service';
// #docregion inject-cart-service, add-to-cart // #docregion inject-cart-service, add-to-cart
export class ProductDetailsComponent implements OnInit { export class ProductDetailsComponent implements OnInit {
// #enddocregion add-to-cart, inject-cart-service // #enddocregion add-to-cart, inject-cart-service
product; product: Product|undefined;
// #docregion inject-cart-service // #docregion inject-cart-service
constructor( constructor(
@ -34,7 +34,7 @@ export class ProductDetailsComponent implements OnInit {
} }
// #docregion add-to-cart // #docregion add-to-cart
addToCart(product) { addToCart(product: Product) {
this.cartService.addToCart(product); this.cartService.addToCart(product);
window.alert('Your product has been added to the cart!'); window.alert('Your product has been added to the cart!');
} }

View File

@ -1,4 +1,11 @@
export const products = [ export interface Product {
id: number;
name: string;
price: number;
description: string;
}
export const products: Product[] = [
{ {
id: 1, id: 1,
name: 'Phone XL', name: 'Phone XL',

View File

@ -5,8 +5,8 @@ import { HeroesService } from './heroes.service';
@Injectable() @Injectable()
export class HeroTaxReturnService { export class HeroTaxReturnService {
private currentTaxReturn: HeroTaxReturn; private currentTaxReturn!: HeroTaxReturn;
private originalTaxReturn: HeroTaxReturn; private originalTaxReturn!: HeroTaxReturn;
constructor(private heroService: HeroesService) { } constructor(private heroService: HeroesService) { }

View File

@ -11,9 +11,9 @@ import { Config, ConfigService } from './config.service';
}) })
export class ConfigComponent { export class ConfigComponent {
error: any; error: any;
headers: string[]; headers: string[] = [];
// #docregion v2 // #docregion v2
config: Config; config: Config | undefined;
// #enddocregion v2 // #enddocregion v2
constructor(private configService: ConfigService) {} constructor(private configService: ConfigService) {}
@ -21,7 +21,7 @@ export class ConfigComponent {
clear() { clear() {
this.config = undefined; this.config = undefined;
this.error = undefined; this.error = undefined;
this.headers = undefined; this.headers = [];
} }
// #docregion v1, v2 // #docregion v1, v2
@ -64,7 +64,7 @@ export class ConfigComponent {
`${key}: ${resp.headers.get(key)}`); `${key}: ${resp.headers.get(key)}`);
// access the body directly, which is typed as `Config`. // access the body directly, which is typed as `Config`.
this.config = { ... resp.body }; this.config = { ...resp.body! };
}); });
} }
// #enddocregion showConfigResponse // #enddocregion showConfigResponse

View File

@ -43,7 +43,7 @@ export class ConfigService {
getConfig_1() { getConfig_1() {
// #docregion getConfig_1 // #docregion getConfig_1
return this.http.get(this.configUrl); return this.http.get<Config>(this.configUrl);
} }
// #enddocregion getConfig_1 // #enddocregion getConfig_1

View File

@ -7,7 +7,7 @@ import { DownloaderService } from './downloader.service';
providers: [ DownloaderService ] providers: [ DownloaderService ]
}) })
export class DownloaderComponent { export class DownloaderComponent {
contents: string; contents: string | undefined;
constructor(private downloaderService: DownloaderService) {} constructor(private downloaderService: DownloaderService) {}
clear() { clear() {

View File

@ -10,8 +10,8 @@ import { HeroesService } from './heroes.service';
styleUrls: ['./heroes.component.css'] styleUrls: ['./heroes.component.css']
}) })
export class HeroesComponent implements OnInit { export class HeroesComponent implements OnInit {
heroes: Hero[]; heroes: Hero[] = [];
editHero: Hero; // the hero currently being edited editHero: Hero | undefined; // the hero currently being edited
constructor(private heroesService: HeroesService) {} constructor(private heroesService: HeroesService) {}

View File

@ -70,7 +70,7 @@ export class HeroesService {
// #docregion deleteHero // #docregion deleteHero
/** DELETE: delete the hero from the server */ /** DELETE: delete the hero from the server */
deleteHero(id: number): Observable<{}> { deleteHero(id: number): Observable<unknown> {
const url = `${this.heroesUrl}/${id}`; // DELETE api/heroes/42 const url = `${this.heroesUrl}/${id}`; // DELETE api/heroes/42
return this.http.delete(url, httpOptions) return this.http.delete(url, httpOptions)
.pipe( .pipe(

View File

@ -2,7 +2,7 @@
<h2>Search Npm Packages</h2> <h2>Search Npm Packages</h2>
<p><i>Searches when typing stops. Caches for 30 seconds.</i></p> <p><i>Searches when typing stops. Caches for 30 seconds.</i></p>
<!-- #docregion search --> <!-- #docregion search -->
<input type="text" (keyup)="search(getValue($event.target))" id="name" placeholder="Search"/> <input type="text" (keyup)="search(getValue($event))" id="name" placeholder="Search"/>
<!-- #enddocregion search --> <!-- #enddocregion search -->
<input type="checkbox" id="refresh" [checked]="withRefresh" (click)="toggleRefresh()"> <input type="checkbox" id="refresh" [checked]="withRefresh" (click)="toggleRefresh()">
<label for="refresh">with refresh</label> <label for="refresh">with refresh</label>

View File

@ -14,7 +14,7 @@ import { NpmPackageInfo, PackageSearchService } from './package-search.service';
export class PackageSearchComponent implements OnInit { export class PackageSearchComponent implements OnInit {
// #docregion debounce // #docregion debounce
withRefresh = false; withRefresh = false;
packages$: Observable<NpmPackageInfo[]>; packages$!: Observable<NpmPackageInfo[]>;
private searchText$ = new Subject<string>(); private searchText$ = new Subject<string>();
search(packageName: string) { search(packageName: string) {
@ -37,8 +37,8 @@ export class PackageSearchComponent implements OnInit {
toggleRefresh() { this.withRefresh = ! this.withRefresh; } toggleRefresh() { this.withRefresh = ! this.withRefresh; }
// #docregion getValue // #docregion getValue
getValue(target: EventTarget): string { getValue(event: Event): string {
return (target as HTMLInputElement).value; return (event.target as HTMLInputElement).value;
} }
// #enddocregion getValue // #enddocregion getValue
} }

View File

@ -14,17 +14,11 @@ export interface NpmPackageInfo {
export const searchUrl = 'https://npmsearch.com/query'; export const searchUrl = 'https://npmsearch.com/query';
const httpOptions = {
headers: new HttpHeaders({
'x-refresh': 'true'
})
};
function createHttpOptions(packageName: string, refresh = false) { function createHttpOptions(packageName: string, refresh = false) {
// npm package name search api // npm package name search api
// e.g., http://npmsearch.com/query?q=dom' // e.g., http://npmsearch.com/query?q=dom'
const params = new HttpParams({ fromObject: { q: packageName } }); const params = new HttpParams({ fromObject: { q: packageName } });
const headerMap = refresh ? {'x-refresh': 'true'} : {}; const headerMap: Record<string, string> = refresh ? {'x-refresh': 'true'} : {};
const headers = new HttpHeaders(headerMap) ; const headers = new HttpHeaders(headerMap) ;
return { headers, params }; return { headers, params };
} }

View File

@ -8,16 +8,16 @@ import { UploaderService } from './uploader.service';
providers: [ UploaderService ] providers: [ UploaderService ]
}) })
export class UploaderComponent { export class UploaderComponent {
message: string; message = '';
constructor(private uploaderService: UploaderService) {} constructor(private uploaderService: UploaderService) {}
onPicked(input: HTMLInputElement) { onPicked(input: HTMLInputElement) {
const file = input.files[0]; const file = input.files?.[0];
if (file) { if (file) {
this.uploaderService.upload(file).subscribe( this.uploaderService.upload(file).subscribe(
msg => { msg => {
input.value = null; input.value = '';
this.message = msg; this.message = msg;
} }
); );

View File

@ -62,7 +62,7 @@ export class UploaderService {
case HttpEventType.UploadProgress: case HttpEventType.UploadProgress:
// Compute and show the % done: // Compute and show the % done:
const percentDone = Math.round(100 * event.loaded / event.total); const percentDone = Math.round(100 * event.loaded / (event.total ?? 0));
return `File "${file.name}" is ${percentDone}% uploaded.`; return `File "${file.name}" is ${percentDone}% uploaded.`;
case HttpEventType.Response: case HttpEventType.Response:

View File

@ -2,7 +2,7 @@ import './testing/global-jasmine';
import 'jasmine-core/lib/jasmine-core/jasmine-html.js'; import 'jasmine-core/lib/jasmine-core/jasmine-html.js';
import 'jasmine-core/lib/jasmine-core/boot.js'; import 'jasmine-core/lib/jasmine-core/boot.js';
declare var jasmine; declare var jasmine: any;
import './polyfills'; import './polyfills';
@ -27,7 +27,7 @@ function bootstrap() {
location.reload(); location.reload();
return; return;
} else { } else {
window.onload(undefined); window.onload?.({} as Event);
(window as any).jasmineRef = jasmine.getEnv(); (window as any).jasmineRef = jasmine.getEnv();
} }

View File

@ -0,0 +1 @@
declare module 'jasmine-core/lib/jasmine-core/jasmine.js';

View File

@ -5,7 +5,7 @@ describe('Inputs and Outputs', () => {
beforeEach(() => browser.get('')); beforeEach(() => browser.get(''));
// helper function used to test what's logged to the console // helper function used to test what's logged to the console
async function logChecker(contents) { async function logChecker(contents: string) {
const logs = await browser const logs = await browser
.manage() .manage()
.logs() .logs()

View File

@ -13,10 +13,10 @@ import { Component, EventEmitter, Input, Output } from '@angular/core';
}) })
export class AliasingComponent { export class AliasingComponent {
input1: string; input1 = '';
outputEvent1: EventEmitter<string> = new EventEmitter<string>(); outputEvent1: EventEmitter<string> = new EventEmitter<string>();
@Input('wishListItem') input2: string; // @Input(alias) @Input('wishListItem') input2 = ''; // @Input(alias)
@Output('wishEvent') outputEvent2 = new EventEmitter<string>(); // @Output(alias) propertyName = ... @Output('wishEvent') outputEvent2 = new EventEmitter<string>(); // @Output(alias) propertyName = ...

View File

@ -34,11 +34,11 @@ export class AppComponent {
console.warn(`Parent says: crossing off ${item}.`); console.warn(`Parent says: crossing off ${item}.`);
} }
buyClearanceItem(item) { buyClearanceItem(item: string) {
console.warn(`Parent says: buying ${item}.`); console.warn(`Parent says: buying ${item}.`);
} }
saveForLater(item) { saveForLater(item: string) {
console.warn(`Parent says: saving ${item} for later.`); console.warn(`Parent says: saving ${item} for later.`);
} }

View File

@ -17,7 +17,7 @@ export class InTheMetadataComponent {
buyEvent = new EventEmitter<string>(); buyEvent = new EventEmitter<string>();
clearanceItem: string; clearanceItem = '';
buyIt() { buyIt() {
console.warn('Child says: emiting buyEvent with', this.clearanceItem); console.warn('Child says: emiting buyEvent with', this.clearanceItem);

View File

@ -6,7 +6,7 @@ import { Component, Input, Output, EventEmitter } from '@angular/core';
styleUrls: ['./input-output.component.css'] styleUrls: ['./input-output.component.css']
}) })
export class InputOutputComponent { export class InputOutputComponent {
@Input() item: string; @Input() item = '';
@Output() deleteRequest = new EventEmitter<string>(); @Output() deleteRequest = new EventEmitter<string>();
lineThrough = ''; lineThrough = '';

View File

@ -11,6 +11,6 @@ import { Component, Input } from '@angular/core'; // First, import Input
// #docregion use-input // #docregion use-input
export class ItemDetailComponent { export class ItemDetailComponent {
@Input() item: string; // decorate the property with @Input() @Input() item = ''; // decorate the property with @Input()
} }
// #enddocregion use-input // #enddocregion use-input

View File

@ -1,3 +1,3 @@
export class Customer { export class Customer {
name: string; name = '';
} }

View File

@ -25,7 +25,7 @@ export class AfterContentComponent implements AfterContentChecked, AfterContentI
comment = ''; comment = '';
// Query for a CONTENT child of type `ChildComponent` // Query for a CONTENT child of type `ChildComponent`
@ContentChild(ChildComponent) contentChild: ChildComponent; @ContentChild(ChildComponent) contentChild!: ChildComponent;
// #enddocregion hooks // #enddocregion hooks
constructor(private logger: LoggerService) { constructor(private logger: LoggerService) {

View File

@ -27,7 +27,7 @@ export class AfterViewComponent implements AfterViewChecked, AfterViewInit {
private prevHero = ''; private prevHero = '';
// Query for a VIEW child of type `ChildViewComponent` // Query for a VIEW child of type `ChildViewComponent`
@ViewChild(ChildViewComponent) viewChild: ChildViewComponent; @ViewChild(ChildViewComponent) viewChild!: ChildViewComponent;
// #enddocregion hooks // #enddocregion hooks
constructor(private logger: LoggerService) { constructor(private logger: LoggerService) {

View File

@ -20,7 +20,7 @@ import { LoggerService } from './logger.service';
providers: [LoggerService] providers: [LoggerService]
}) })
export class CounterParentComponent { export class CounterParentComponent {
value: number; value = 0;
spyLog: string[] = []; spyLog: string[] = [];
private logger: LoggerService; private logger: LoggerService;

View File

@ -16,7 +16,7 @@ import {
` `
}) })
export class MyCounterComponent implements OnChanges { export class MyCounterComponent implements OnChanges {
@Input() counter: number; @Input() counter = 0;
changeLog: string[] = []; changeLog: string[] = [];
ngOnChanges(changes: SimpleChanges) { ngOnChanges(changes: SimpleChanges) {

View File

@ -8,10 +8,10 @@ import { Hero } from './hero';
templateUrl: './do-check-parent.component.html' templateUrl: './do-check-parent.component.html'
}) })
export class DoCheckParentComponent { export class DoCheckParentComponent {
hero: Hero; hero!: Hero;
power: string; power = '';
title = 'DoCheck'; title = 'DoCheck';
@ViewChild(DoCheckComponent) childView: DoCheckComponent; @ViewChild(DoCheckComponent) childView!: DoCheckComponent;
constructor() { constructor() {
this.reset(); this.reset();

View File

@ -16,8 +16,8 @@ import { Hero } from './hero';
` `
}) })
export class DoCheckComponent implements DoCheck { export class DoCheckComponent implements DoCheck {
@Input() hero: Hero; @Input() hero!: Hero;
@Input() power: string; @Input() power = '';
changeDetected = false; changeDetected = false;
changeLog: string[] = []; changeLog: string[] = [];

View File

@ -9,10 +9,10 @@ import { OnChangesComponent } from './on-changes.component';
styles: [''] styles: ['']
}) })
export class OnChangesParentComponent { export class OnChangesParentComponent {
hero: Hero; hero!: Hero;
power: string; power = '';
title = 'OnChanges'; title = 'OnChanges';
@ViewChild(OnChangesComponent) childView: OnChangesComponent; @ViewChild(OnChangesComponent) childView!: OnChangesComponent;
constructor() { constructor() {
this.reset(); this.reset();

View File

@ -17,8 +17,8 @@ import { Hero } from './hero';
}) })
export class OnChangesComponent implements OnChanges { export class OnChangesComponent implements OnChanges {
// #docregion inputs // #docregion inputs
@Input() hero: Hero; @Input() hero!: Hero;
@Input() power: string; @Input() power = '';
// #enddocregion inputs // #enddocregion inputs
changeLog: string[] = []; changeLog: string[] = [];

View File

@ -28,7 +28,7 @@ import { LoggerService } from './logger.service';
export class PeekABooParentComponent { export class PeekABooParentComponent {
hasChild = false; hasChild = false;
hookLog: string[]; hookLog: string[] = [];
heroName = 'Windstorm'; heroName = 'Windstorm';
private logger: LoggerService; private logger: LoggerService;

View File

@ -28,7 +28,7 @@ export class PeekABooComponent extends PeekABooDirective implements
AfterContentInit, AfterContentChecked, AfterContentInit, AfterContentChecked,
AfterViewInit, AfterViewChecked, AfterViewInit, AfterViewChecked,
OnDestroy { OnDestroy {
@Input() name: string; @Input() name = '';
private verb = 'initialized'; private verb = 'initialized';

View File

@ -1,7 +1,7 @@
// #docregion // #docregion
import { Component } from '@angular/core'; import { Component } from '@angular/core';
import { heroes } from './hero'; import { Hero, heroes } from './hero';
@Component({ @Component({
selector: 'app-root', selector: 'app-root',
@ -10,7 +10,7 @@ import { heroes } from './hero';
}) })
export class AppComponent { export class AppComponent {
heroes = heroes; heroes = heroes;
hero = this.heroes[0]; hero: Hero | null = this.heroes[0];
heroTraits = ['honest', 'brave', 'considerate']; heroTraits = ['honest', 'brave', 'considerate'];
// flags for the table // flags for the table

View File

@ -8,7 +8,7 @@ import { Hero } from './hero';
template: `Wow. You like {{hero.name}}. What a happy hero ... just like you.` template: `Wow. You like {{hero.name}}. What a happy hero ... just like you.`
}) })
export class HappyHeroComponent { export class HappyHeroComponent {
@Input() hero: Hero; @Input() hero!: Hero;
} }
@Component({ @Component({
@ -16,7 +16,7 @@ export class HappyHeroComponent {
template: `You like {{hero.name}}? Such a sad hero. Are you sad too?` template: `You like {{hero.name}}? Such a sad hero. Are you sad too?`
}) })
export class SadHeroComponent { export class SadHeroComponent {
@Input() hero: Hero; @Input() hero!: Hero;
} }
@Component({ @Component({
@ -24,7 +24,7 @@ export class SadHeroComponent {
template: `Are you as confused as {{hero.name}}?` template: `Are you as confused as {{hero.name}}?`
}) })
export class ConfusedHeroComponent { export class ConfusedHeroComponent {
@Input() hero: Hero; @Input() hero!: Hero;
} }
@Component({ @Component({
@ -32,7 +32,7 @@ export class ConfusedHeroComponent {
template: `{{message}}` template: `{{message}}`
}) })
export class UnknownHeroComponent { export class UnknownHeroComponent {
@Input() hero: Hero; @Input() hero!: Hero;
get message() { get message() {
return this.hero && this.hero.name return this.hero && this.hero.name
? `${this.hero.name} is strange and mysterious.` ? `${this.hero.name} is strange and mysterious.`

Some files were not shown because too many files have changed in this diff Show More