
add e2e test for SVG template example fix template syntax example app - linting errors - runtime exceptions - template type errors - deprecated type casting - deprecated currency pipe example Relates to #30559 PR Close #31356
189 lines
5.3 KiB
TypeScript
189 lines
5.3 KiB
TypeScript
/* tslint:disable:forin member-ordering */
|
|
// #docplaster
|
|
|
|
import { AfterViewInit, Component, ElementRef, OnInit, QueryList, ViewChildren } from '@angular/core';
|
|
|
|
import { Hero } from './hero';
|
|
|
|
export enum Color {Red, Green, Blue}
|
|
|
|
/**
|
|
* Giant grab bag of stuff to drive the chapter
|
|
*/
|
|
@Component({
|
|
selector: 'app-root',
|
|
templateUrl: './app.component.html',
|
|
styleUrls: [ './app.component.css' ]
|
|
})
|
|
export class AppComponent implements AfterViewInit, OnInit {
|
|
|
|
ngOnInit() {
|
|
this.resetHeroes();
|
|
this.setCurrentClasses();
|
|
this.setCurrentStyles();
|
|
}
|
|
|
|
ngAfterViewInit() {
|
|
// Detect effects of NgForTrackBy
|
|
trackChanges(this.heroesNoTrackBy, () => this.heroesNoTrackByCount++);
|
|
trackChanges(this.heroesWithTrackBy, () => this.heroesWithTrackByCount++);
|
|
}
|
|
|
|
@ViewChildren('noTrackBy') heroesNoTrackBy: QueryList<ElementRef>;
|
|
@ViewChildren('withTrackBy') heroesWithTrackBy: QueryList<ElementRef>;
|
|
|
|
actionName = 'Go for it';
|
|
badCurly = 'bad curly';
|
|
classes = 'special';
|
|
help = '';
|
|
|
|
alert(msg?: string) { window.alert(msg); }
|
|
callFax(value: string) { this.alert(`Faxing ${value} ...`); }
|
|
callPhone(value: string) { this.alert(`Calling ${value} ...`); }
|
|
canSave = true;
|
|
|
|
changeIds() {
|
|
this.resetHeroes();
|
|
this.heroes.forEach(h => h.id += 10 * this.heroIdIncrement++);
|
|
this.heroesWithTrackByCountReset = -1;
|
|
}
|
|
|
|
clearTrackByCounts() {
|
|
const trackByCountReset = this.heroesWithTrackByCountReset;
|
|
this.resetHeroes();
|
|
this.heroesNoTrackByCount = -1;
|
|
this.heroesWithTrackByCount = trackByCountReset;
|
|
this.heroIdIncrement = 1;
|
|
}
|
|
|
|
clicked = '';
|
|
clickMessage = '';
|
|
clickMessage2 = '';
|
|
|
|
Color = Color;
|
|
color = Color.Red;
|
|
colorToggle() {this.color = (this.color === Color.Red) ? Color.Blue : Color.Red; }
|
|
|
|
currentHero: Hero;
|
|
|
|
updateCurrentHeroName(event: Event) {
|
|
this.currentHero.name = (event.target as any).value;
|
|
}
|
|
|
|
deleteHero(hero?: Hero) {
|
|
this.alert(`Delete ${hero ? hero.name : 'the hero'}.`);
|
|
}
|
|
|
|
// #docregion evil-title
|
|
evilTitle = 'Template <script>alert("evil never sleeps")</script>Syntax';
|
|
// #enddocregion evil-title
|
|
|
|
fontSizePx = 16;
|
|
|
|
title = 'Template Syntax';
|
|
|
|
getVal(): number { return 2; }
|
|
|
|
name: string = Hero.heroes[0].name;
|
|
hero: Hero; // defined to demonstrate template context precedence
|
|
heroes: Hero[];
|
|
|
|
// trackBy change counting
|
|
heroesNoTrackByCount = 0;
|
|
heroesWithTrackByCount = 0;
|
|
heroesWithTrackByCountReset = 0;
|
|
|
|
heroIdIncrement = 1;
|
|
|
|
// heroImageUrl = 'http://www.wpclipart.com/cartoon/people/hero/hero_silhoutte_T.png';
|
|
// Public Domain terms of use: http://www.wpclipart.com/terms.html
|
|
heroImageUrl = 'assets/images/hero.png';
|
|
// villainImageUrl = 'http://www.clker.com/cliparts/u/s/y/L/x/9/villain-man-hi.png'
|
|
// Public Domain terms of use http://www.clker.com/disclaimer.html
|
|
villainImageUrl = 'assets/images/villain.png';
|
|
|
|
iconUrl = 'assets/images/ng-logo.png';
|
|
isActive = false;
|
|
isSpecial = true;
|
|
isUnchanged = true;
|
|
|
|
get nullHero(): Hero { return null; }
|
|
|
|
onClickMe(event?: MouseEvent) {
|
|
const evtMsg = event ? ' Event target class is ' + (event.target as HTMLElement).className : '';
|
|
this.alert('Click me.' + evtMsg);
|
|
}
|
|
|
|
onSave(event?: MouseEvent) {
|
|
const evtMsg = event ? ' Event target is ' + (event.target as HTMLElement).textContent : '';
|
|
this.alert('Saved.' + evtMsg);
|
|
if (event) { event.stopPropagation(); }
|
|
}
|
|
|
|
onSubmit(data: any) {/* referenced but not used */}
|
|
|
|
product = {
|
|
name: 'frimfram',
|
|
price: 42
|
|
};
|
|
|
|
// updates with fresh set of cloned heroes
|
|
resetHeroes() {
|
|
this.heroes = Hero.heroes.map(hero => hero.clone());
|
|
this.currentHero = this.heroes[0];
|
|
this.hero = this.currentHero;
|
|
this.heroesWithTrackByCountReset = 0;
|
|
}
|
|
|
|
setUppercaseName(name: string) {
|
|
this.currentHero.name = name.toUpperCase();
|
|
}
|
|
|
|
// #docregion setClasses
|
|
currentClasses: {};
|
|
setCurrentClasses() {
|
|
// CSS classes: added/removed per current state of component properties
|
|
this.currentClasses = {
|
|
saveable: this.canSave,
|
|
modified: !this.isUnchanged,
|
|
special: this.isSpecial
|
|
};
|
|
}
|
|
// #enddocregion setClasses
|
|
|
|
// #docregion setStyles
|
|
currentStyles: {};
|
|
setCurrentStyles() {
|
|
// CSS styles: set per current state of component properties
|
|
this.currentStyles = {
|
|
'font-style': this.canSave ? 'italic' : 'normal',
|
|
'font-weight': !this.isUnchanged ? 'bold' : 'normal',
|
|
'font-size': this.isSpecial ? '24px' : '12px'
|
|
};
|
|
}
|
|
// #enddocregion setStyles
|
|
|
|
// #docregion trackByHeroes
|
|
trackByHeroes(index: number, hero: Hero): number { return hero.id; }
|
|
// #enddocregion trackByHeroes
|
|
|
|
// #docregion trackById
|
|
trackById(index: number, item: any): number { return item.id; }
|
|
// #enddocregion trackById
|
|
}
|
|
|
|
// helper to track changes to viewChildren
|
|
function trackChanges(views: QueryList<ElementRef>, changed: () => void) {
|
|
let oldRefs = views.toArray();
|
|
views.changes.subscribe((changes: QueryList<ElementRef>) => {
|
|
const changedRefs = changes.toArray();
|
|
// Check if every changed Element is the same as old and in the same position
|
|
const isSame = oldRefs.every((v, i) => v.nativeElement === changedRefs[i].nativeElement);
|
|
if (!isSame) {
|
|
oldRefs = changedRefs;
|
|
// wait a tick because called after views are constructed
|
|
setTimeout(changed, 0);
|
|
}
|
|
});
|
|
}
|