build(docs-infra): implement full template checking for examples (#40930)

This commit turns on full template type checking and fixes the examples
that had errors.

PR Close #40930
This commit is contained in:
Pete Bacon Darwin 2021-02-20 16:30:31 +00:00 committed by Zach Arend
parent 03d92f75e6
commit 4859c0947a
13 changed files with 51 additions and 20 deletions

View File

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

View File

@ -114,6 +114,9 @@ export class AppComponent implements OnInit {
trackById(index: number, item: any): number { return item.id; }
getValue(target: EventTarget): string {
return (target as HTMLInputElement).value;
}
}

View File

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

View File

@ -11,7 +11,7 @@ export class AppComponent {
currentItem = { name: 'teapot'} ;
clickMessage = '';
onSave(event?: KeyboardEvent) {
onSave(event?: MouseEvent) {
const evtMsg = event ? ' Event target is ' + (event.target as HTMLElement).textContent : '';
alert('Saved.' + evtMsg);
if (event) { event.stopPropagation(); }
@ -21,9 +21,14 @@ export class AppComponent {
alert(`Delete the ${item.name}.`);
}
onClickMe(event?: KeyboardEvent) {
onClickMe(event?: MouseEvent) {
const evtMsg = event ? ' Event target class is ' + (event.target as HTMLElement).className : '';
alert('Click me.' + evtMsg);
}
// #docregion getValue
getValue(target: EventTarget): string {
return (target as HTMLInputElement).value;
}
// #enddocregion getValue
}

View File

@ -1,14 +1,15 @@
// #docplaster
// #docregion import-http
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
// #enddocregion import-http
@Injectable({
providedIn: 'root'
})
// #docregion props, methods, inject-http, get-shipping
export class CartService {
// #enddocregion get-shipping
items = [];
// #enddocregion props, methods
@ -32,8 +33,10 @@ export class CartService {
}
// #enddocregion methods
// #docregion get-shipping
getShippingPrices() {
return this.http.get('/assets/shipping.json');
return this.http.get<{type: string, price: number}[]>('/assets/shipping.json');
}
// #docregion props, methods, inject-http
}
// #enddocregion props, methods, inject-http

View File

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

View File

@ -35,4 +35,9 @@ export class PackageSearchComponent implements OnInit {
toggleRefresh() { this.withRefresh = ! this.withRefresh; }
// #docregion getValue
getValue(target: EventTarget): string {
return (target as HTMLInputElement).value;
}
// #enddocregion getValue
}

View File

@ -3,11 +3,11 @@
// #docregion pure
import { Pipe, PipeTransform } from '@angular/core';
import { Flyer } from './heroes';
import { Hero } from './heroes';
@Pipe({ name: 'flyingHeroes' })
export class FlyingHeroesPipe implements PipeTransform {
transform(allHeroes: Flyer[]) {
transform(allHeroes: Hero[]) {
// #docregion filter
return allHeroes.filter(hero => hero.canFly);
// #enddocregion filter

View File

@ -1,5 +1,5 @@
export interface Flyer { canFly: boolean; }
export const HEROES = [
export interface Hero { name: string; canFly: boolean; }
export const HEROES: Hero[] = [
{name: 'Windstorm', canFly: true},
{name: 'Bombasto', canFly: false},
{name: 'Magneto', canFly: false},

View File

@ -219,11 +219,9 @@ button</button>
<app-hero-detail [hero]="currentHero"></app-hero-detail>
<img bind-src="heroImageUrl">
<!-- ERROR: HeroDetailComponent.hero expects a
Hero object, not the string "currentHero" -->
<div *ngIf="false">
<app-hero-detail hero="currentHero"></app-hero-detail>
</div>
<!-- ERROR: HeroDetailComponent.hero expects a Hero object, not the string "currentHero" -->
<!-- <app-hero-detail hero="currentHero"></app-hero-detail> -->
<app-hero-detail prefix="You are my" [hero]="currentHero"></app-hero-detail>
<p><img src="{{heroImageUrl}}"> is the <i>interpolated</i> image.</p>

View File

@ -25,7 +25,15 @@ With this example, the following actions occur:
1. The code binds to the `input` event of the `<input>` element, which allows the code to listen for changes.
1. When the user makes changes, the component raises the `input` event.
1. The binding executes the statement within a context that includes the DOM event object, `$event`.
1. Angular retrieves the changed text by following the path `$event.target.value` and updates the `name` property.
1. Angular retrieves the changed text by calling `getValue($event.target)` and updates the `name` property.
If the event belongs to a directive or component, `$event` has the shape that the directive or component produces.
<div class="alert is-helpful">
The type of `$event.target` is only `EventTarget` in the template.
In the `getValue()` method, the target is cast to an `HTMLInputElement` to allow type-safe access to its `value` property.
<code-example path="event-binding/src/app/app.component.ts" region="getValue"></code-example>
</div>

View File

@ -978,6 +978,16 @@ a search request for a package with that name to the npm web API.
</code-example>
Here, the `keyup` event binding sends every keystroke to the component's `search()` method.
<div class="alert is-helpful">
The type of `$event.target` is only `EventTarget` in the template.
In the `getValue()` method, the target is cast to an `HTMLInputElement` to allow type-safe access to its `value` property.
<code-example path="http/src/app/package-search/package-search.component.ts" region="getValue"></code-example>
</div>
The following snippet implements debouncing for this input using RxJS operators.
<code-example

View File

@ -25,7 +25,6 @@
"angularCompilerOptions": {
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
// TODO(gkalpak): Fix the code and enable this (i.e. switch from `fullTemplateTypeCheck` to `strictTemplates`).
"fullTemplateTypeCheck": true,// "strictTemplates": true
"strictTemplates": true
}
}