973 lines
32 KiB
HTML
973 lines
32 KiB
HTML
|
<html lang="en"><head></head><body>
|
||
|
<form id="mainForm" method="post" action="https://run.stackblitz.com/api/angular/v1?file=src/app/app.component.html" target="_self"><input type="hidden" name="files[src/app/app.component.ts]" value="import { Component } from '@angular/core';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-root',
|
||
|
templateUrl: './app.component.html'
|
||
|
})
|
||
|
export class AppComponent { }
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/app.module.ts]" value="import { NgModule } from '@angular/core';
|
||
|
import { BrowserModule } from '@angular/platform-browser';
|
||
|
|
||
|
import { AppComponent } from './app.component';
|
||
|
import { AstronautComponent } from './astronaut.component';
|
||
|
import { CountdownLocalVarParentComponent, CountdownViewChildParentComponent } from './countdown-parent.component';
|
||
|
import { CountdownTimerComponent } from './countdown-timer.component';
|
||
|
import { HeroChildComponent } from './hero-child.component';
|
||
|
import { HeroParentComponent } from './hero-parent.component';
|
||
|
import { MissionControlComponent } from './missioncontrol.component';
|
||
|
import { NameChildComponent } from './name-child.component';
|
||
|
import { NameParentComponent } from './name-parent.component';
|
||
|
import { VersionChildComponent } from './version-child.component';
|
||
|
import { VersionParentComponent } from './version-parent.component';
|
||
|
import { VoterComponent } from './voter.component';
|
||
|
import { VoteTakerComponent } from './votetaker.component';
|
||
|
|
||
|
|
||
|
@NgModule({
|
||
|
imports: [
|
||
|
BrowserModule,
|
||
|
],
|
||
|
declarations: [
|
||
|
AppComponent,
|
||
|
AstronautComponent,
|
||
|
CountdownLocalVarParentComponent,
|
||
|
CountdownTimerComponent,
|
||
|
CountdownViewChildParentComponent,
|
||
|
HeroChildComponent,
|
||
|
HeroParentComponent,
|
||
|
MissionControlComponent,
|
||
|
NameChildComponent,
|
||
|
NameParentComponent,
|
||
|
VersionChildComponent,
|
||
|
VersionParentComponent,
|
||
|
VoterComponent,
|
||
|
VoteTakerComponent,
|
||
|
],
|
||
|
bootstrap: [ AppComponent ],
|
||
|
})
|
||
|
export class AppModule { }
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/astronaut.component.ts]" value="import { Component, Input, OnDestroy } from '@angular/core';
|
||
|
|
||
|
import { MissionService } from './mission.service';
|
||
|
import { Subscription } from 'rxjs';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-astronaut',
|
||
|
template: `
|
||
|
<p>
|
||
|
{{astronaut}}: <strong>{{mission}}</strong>
|
||
|
<button
|
||
|
(click)="confirm()"
|
||
|
[disabled]="!announced || confirmed">
|
||
|
Confirm
|
||
|
</button>
|
||
|
</p>
|
||
|
`
|
||
|
})
|
||
|
export class AstronautComponent implements OnDestroy {
|
||
|
@Input() astronaut: string;
|
||
|
mission = '<no mission announced>';
|
||
|
confirmed = false;
|
||
|
announced = false;
|
||
|
subscription: Subscription;
|
||
|
|
||
|
constructor(private missionService: MissionService) {
|
||
|
this.subscription = missionService.missionAnnounced$.subscribe(
|
||
|
mission => {
|
||
|
this.mission = mission;
|
||
|
this.announced = true;
|
||
|
this.confirmed = false;
|
||
|
});
|
||
|
}
|
||
|
|
||
|
confirm() {
|
||
|
this.confirmed = true;
|
||
|
this.missionService.confirmMission(this.astronaut);
|
||
|
}
|
||
|
|
||
|
ngOnDestroy() {
|
||
|
// prevent memory leak when component destroyed
|
||
|
this.subscription.unsubscribe();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/countdown-parent.component.ts]" value="import { AfterViewInit, ViewChild } from '@angular/core';
|
||
|
import { Component } from '@angular/core';
|
||
|
import { CountdownTimerComponent } from './countdown-timer.component';
|
||
|
|
||
|
|
||
|
//// Local variable, #timer, version
|
||
|
@Component({
|
||
|
selector: 'app-countdown-parent-lv',
|
||
|
template: `
|
||
|
<h3>Countdown to Liftoff (via local variable)</h3>
|
||
|
<button (click)="timer.start()">Start</button>
|
||
|
<button (click)="timer.stop()">Stop</button>
|
||
|
<div class="seconds">{{timer.seconds}}</div>
|
||
|
<app-countdown-timer #timer></app-countdown-timer>
|
||
|
`,
|
||
|
styleUrls: ['../assets/demo.css']
|
||
|
})
|
||
|
export class CountdownLocalVarParentComponent { }
|
||
|
|
||
|
//// View Child version
|
||
|
@Component({
|
||
|
selector: 'app-countdown-parent-vc',
|
||
|
template: `
|
||
|
<h3>Countdown to Liftoff (via ViewChild)</h3>
|
||
|
<button (click)="start()">Start</button>
|
||
|
<button (click)="stop()">Stop</button>
|
||
|
<div class="seconds">{{ seconds() }}</div>
|
||
|
<app-countdown-timer></app-countdown-timer>
|
||
|
`,
|
||
|
styleUrls: ['../assets/demo.css']
|
||
|
})
|
||
|
export class CountdownViewChildParentComponent implements AfterViewInit {
|
||
|
|
||
|
@ViewChild(CountdownTimerComponent)
|
||
|
private timerComponent: CountdownTimerComponent;
|
||
|
|
||
|
seconds() { return 0; }
|
||
|
|
||
|
ngAfterViewInit() {
|
||
|
// Redefine `seconds()` to get from the `CountdownTimerComponent.seconds` ...
|
||
|
// but wait a tick first to avoid one-time devMode
|
||
|
// unidirectional-data-flow-violation error
|
||
|
setTimeout(() => this.seconds = () => this.timerComponent.seconds, 0);
|
||
|
}
|
||
|
|
||
|
start() { this.timerComponent.start(); }
|
||
|
stop() { this.timerComponent.stop(); }
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/countdown-timer.component.ts]" value="import { Component, OnDestroy } from '@angular/core';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-countdown-timer',
|
||
|
template: '<p>{{message}}</p>'
|
||
|
})
|
||
|
export class CountdownTimerComponent implements OnDestroy {
|
||
|
|
||
|
intervalId = 0;
|
||
|
message = '';
|
||
|
seconds = 11;
|
||
|
|
||
|
ngOnDestroy() { this.clearTimer(); }
|
||
|
|
||
|
start() { this.countDown(); }
|
||
|
stop() {
|
||
|
this.clearTimer();
|
||
|
this.message = `Holding at T-${this.seconds} seconds`;
|
||
|
}
|
||
|
|
||
|
private clearTimer() { clearInterval(this.intervalId); }
|
||
|
|
||
|
private countDown() {
|
||
|
this.clearTimer();
|
||
|
this.intervalId = window.setInterval(() => {
|
||
|
this.seconds -= 1;
|
||
|
if (this.seconds === 0) {
|
||
|
this.message = 'Blast off!';
|
||
|
} else {
|
||
|
if (this.seconds < 0) { this.seconds = 10; } // reset
|
||
|
this.message = `T-${this.seconds} seconds and counting`;
|
||
|
}
|
||
|
}, 1000);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/hero-child.component.ts]" value="import { Component, Input } from '@angular/core';
|
||
|
|
||
|
import { Hero } from './hero';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-hero-child',
|
||
|
template: `
|
||
|
<h3>{{hero.name}} says:</h3>
|
||
|
<p>I, {{hero.name}}, am at your service, {{masterName}}.</p>
|
||
|
`
|
||
|
})
|
||
|
export class HeroChildComponent {
|
||
|
@Input() hero: Hero;
|
||
|
@Input('master') masterName: string; // tslint:disable-line: no-input-rename
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/hero-parent.component.ts]" value="import { Component } from '@angular/core';
|
||
|
|
||
|
import { HEROES } from './hero';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-hero-parent',
|
||
|
template: `
|
||
|
<h2>{{master}} controls {{heroes.length}} heroes</h2>
|
||
|
<app-hero-child *ngFor="let hero of heroes"
|
||
|
[hero]="hero"
|
||
|
[master]="master">
|
||
|
</app-hero-child>
|
||
|
`
|
||
|
})
|
||
|
export class HeroParentComponent {
|
||
|
heroes = HEROES;
|
||
|
master = 'Master';
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/hero.ts]" value="export interface Hero {
|
||
|
name: string;
|
||
|
}
|
||
|
|
||
|
export const HEROES = [
|
||
|
{name: 'Dr IQ'},
|
||
|
{name: 'Magneta'},
|
||
|
{name: 'Bombasto'}
|
||
|
];
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/mission.service.ts]" value="import { Injectable } from '@angular/core';
|
||
|
import { Subject } from 'rxjs';
|
||
|
|
||
|
@Injectable()
|
||
|
export class MissionService {
|
||
|
|
||
|
// Observable string sources
|
||
|
private missionAnnouncedSource = new Subject<string>();
|
||
|
private missionConfirmedSource = new Subject<string>();
|
||
|
|
||
|
// Observable string streams
|
||
|
missionAnnounced$ = this.missionAnnouncedSource.asObservable();
|
||
|
missionConfirmed$ = this.missionConfirmedSource.asObservable();
|
||
|
|
||
|
// Service message commands
|
||
|
announceMission(mission: string) {
|
||
|
this.missionAnnouncedSource.next(mission);
|
||
|
}
|
||
|
|
||
|
confirmMission(astronaut: string) {
|
||
|
this.missionConfirmedSource.next(astronaut);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/missioncontrol.component.ts]" value="import { Component } from '@angular/core';
|
||
|
|
||
|
import { MissionService } from './mission.service';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-mission-control',
|
||
|
template: `
|
||
|
<h2>Mission Control</h2>
|
||
|
<button (click)="announce()">Announce mission</button>
|
||
|
<app-astronaut *ngFor="let astronaut of astronauts"
|
||
|
[astronaut]="astronaut">
|
||
|
</app-astronaut>
|
||
|
<h3>History</h3>
|
||
|
<ul>
|
||
|
<li *ngFor="let event of history">{{event}}</li>
|
||
|
</ul>
|
||
|
`,
|
||
|
providers: [MissionService]
|
||
|
})
|
||
|
export class MissionControlComponent {
|
||
|
astronauts = ['Lovell', 'Swigert', 'Haise'];
|
||
|
history: string[] = [];
|
||
|
missions = ['Fly to the moon!',
|
||
|
'Fly to mars!',
|
||
|
'Fly to Vegas!'];
|
||
|
nextMission = 0;
|
||
|
|
||
|
constructor(private missionService: MissionService) {
|
||
|
missionService.missionConfirmed$.subscribe(
|
||
|
astronaut => {
|
||
|
this.history.push(`${astronaut} confirmed the mission`);
|
||
|
});
|
||
|
}
|
||
|
|
||
|
announce() {
|
||
|
const mission = this.missions[this.nextMission++];
|
||
|
this.missionService.announceMission(mission);
|
||
|
this.history.push(`Mission "${mission}" announced`);
|
||
|
if (this.nextMission >= this.missions.length) { this.nextMission = 0; }
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/name-child.component.ts]" value="// tslint:disable: variable-name
|
||
|
import { Component, Input } from '@angular/core';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-name-child',
|
||
|
template: '<h3>"{{name}}"</h3>'
|
||
|
})
|
||
|
export class NameChildComponent {
|
||
|
@Input()
|
||
|
get name(): string { return this._name; }
|
||
|
set name(name: string) {
|
||
|
this._name = (name && name.trim()) || '<no name set>';
|
||
|
}
|
||
|
private _name = '';
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/name-parent.component.ts]" value="import { Component } from '@angular/core';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-name-parent',
|
||
|
template: `
|
||
|
<h2>Master controls {{names.length}} names</h2>
|
||
|
<app-name-child *ngFor="let name of names" [name]="name"></app-name-child>
|
||
|
`
|
||
|
})
|
||
|
export class NameParentComponent {
|
||
|
// Displays 'Dr IQ', '<no name set>', 'Bombasto'
|
||
|
names = ['Dr IQ', ' ', ' Bombasto '];
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/version-child.component.ts]" value="/* tslint:disable:forin */
|
||
|
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-version-child',
|
||
|
template: `
|
||
|
<h3>Version {{major}}.{{minor}}</h3>
|
||
|
<h4>Change log:</h4>
|
||
|
<ul>
|
||
|
<li *ngFor="let change of changeLog">{{change}}</li>
|
||
|
</ul>
|
||
|
`
|
||
|
})
|
||
|
export class VersionChildComponent implements OnChanges {
|
||
|
@Input() major: number;
|
||
|
@Input() minor: number;
|
||
|
changeLog: string[] = [];
|
||
|
|
||
|
ngOnChanges(changes: SimpleChanges) {
|
||
|
const log: string[] = [];
|
||
|
for (const propName in changes) {
|
||
|
const changedProp = changes[propName];
|
||
|
const to = JSON.stringify(changedProp.currentValue);
|
||
|
if (changedProp.isFirstChange()) {
|
||
|
log.push(`Initial value of ${propName} set to ${to}`);
|
||
|
} else {
|
||
|
const from = JSON.stringify(changedProp.previousValue);
|
||
|
log.push(`${propName} changed from ${from} to ${to}`);
|
||
|
}
|
||
|
}
|
||
|
this.changeLog.push(log.join(', '));
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/version-parent.component.ts]" value="import { Component } from '@angular/core';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-version-parent',
|
||
|
template: `
|
||
|
<h2>Source code version</h2>
|
||
|
<button (click)="newMinor()">New minor version</button>
|
||
|
<button (click)="newMajor()">New major version</button>
|
||
|
<app-version-child [major]="major" [minor]="minor"></app-version-child>
|
||
|
`
|
||
|
})
|
||
|
export class VersionParentComponent {
|
||
|
major = 1;
|
||
|
minor = 23;
|
||
|
|
||
|
newMinor() {
|
||
|
this.minor++;
|
||
|
}
|
||
|
|
||
|
newMajor() {
|
||
|
this.major++;
|
||
|
this.minor = 0;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/voter.component.ts]" value="import { Component, EventEmitter, Input, Output } from '@angular/core';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-voter',
|
||
|
template: `
|
||
|
<h4>{{name}}</h4>
|
||
|
<button (click)="vote(true)" [disabled]="didVote">Agree</button>
|
||
|
<button (click)="vote(false)" [disabled]="didVote">Disagree</button>
|
||
|
`
|
||
|
})
|
||
|
export class VoterComponent {
|
||
|
@Input() name: string;
|
||
|
@Output() voted = new EventEmitter<boolean>();
|
||
|
didVote = false;
|
||
|
|
||
|
vote(agreed: boolean) {
|
||
|
this.voted.emit(agreed);
|
||
|
this.didVote = true;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/votetaker.component.ts]" value="import { Component } from '@angular/core';
|
||
|
|
||
|
@Component({
|
||
|
selector: 'app-vote-taker',
|
||
|
template: `
|
||
|
<h2>Should mankind colonize the Universe?</h2>
|
||
|
<h3>Agree: {{agreed}}, Disagree: {{disagreed}}</h3>
|
||
|
<app-voter *ngFor="let voter of voters"
|
||
|
[name]="voter"
|
||
|
(voted)="onVoted($event)">
|
||
|
</app-voter>
|
||
|
`
|
||
|
})
|
||
|
export class VoteTakerComponent {
|
||
|
agreed = 0;
|
||
|
disagreed = 0;
|
||
|
voters = ['Narco', 'Celeritas', 'Bombasto'];
|
||
|
|
||
|
onVoted(agreed: boolean) {
|
||
|
agreed ? this.agreed++ : this.disagreed++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/environments/environment.prod.ts]" value="export const environment = {
|
||
|
production: true
|
||
|
};
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/environments/environment.ts]" value="// This file can be replaced during build by using the `fileReplacements` array.
|
||
|
// `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
|
||
|
// The list of file replacements can be found in `angular.json`.
|
||
|
|
||
|
export const environment = {
|
||
|
production: false
|
||
|
};
|
||
|
|
||
|
/*
|
||
|
* For easier debugging in development mode, you can import the following file
|
||
|
* to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
|
||
|
*
|
||
|
* This import should be commented out in production mode because it will have a negative impact
|
||
|
* on performance if an error is thrown.
|
||
|
*/
|
||
|
// import 'zone.js/plugins/zone-error'; // Included with Angular CLI.
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/main.ts]" value="import { enableProdMode } from '@angular/core';
|
||
|
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
|
||
|
|
||
|
import { AppModule } from './app/app.module';
|
||
|
import { environment } from './environments/environment';
|
||
|
|
||
|
if (environment.production) {
|
||
|
enableProdMode();
|
||
|
}
|
||
|
|
||
|
platformBrowserDynamic().bootstrapModule(AppModule);
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/polyfills.ts]" value="/**
|
||
|
* This file includes polyfills needed by Angular and is loaded before the app.
|
||
|
* You can add your own extra polyfills to this file.
|
||
|
*
|
||
|
* This file is divided into 2 sections:
|
||
|
* 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
|
||
|
* 2. Application imports. Files imported after ZoneJS that should be loaded before your main
|
||
|
* file.
|
||
|
*
|
||
|
* The current setup is for so-called "evergreen" browsers; the last versions of browsers that
|
||
|
* automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
|
||
|
* Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
|
||
|
*
|
||
|
* Learn more in https://angular.io/guide/browser-support
|
||
|
*/
|
||
|
|
||
|
/***************************************************************************************************
|
||
|
* BROWSER POLYFILLS
|
||
|
*/
|
||
|
|
||
|
/** IE11 requires the following for NgClass support on SVG elements */
|
||
|
// import 'classlist.js'; // Run `npm install --save classlist.js`.
|
||
|
|
||
|
/**
|
||
|
* Web Animations `@angular/platform-browser/animations`
|
||
|
* Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
|
||
|
* Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
|
||
|
*/
|
||
|
// import 'web-animations-js'; // Run `npm install --save web-animations-js`.
|
||
|
|
||
|
/**
|
||
|
* By default, zone.js will patch all possible macroTask and DomEvents
|
||
|
* user can disable parts of macroTask/DomEvents patch by setting following flags
|
||
|
* because those flags need to be set before `zone.js` being loaded, and webpack
|
||
|
* will put import in the top of bundle, so user need to create a separate file
|
||
|
* in this directory (for example: zone-flags.ts), and put the following flags
|
||
|
* into that file, and then add the following code before importing zone.js.
|
||
|
* import './zone-flags';
|
||
|
*
|
||
|
* The flags allowed in zone-flags.ts are listed here.
|
||
|
*
|
||
|
* The following flags will work for all browsers.
|
||
|
*
|
||
|
* (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch
|
||
|
* requestAnimationFrame
|
||
|
* (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
|
||
|
* (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch
|
||
|
* specified eventNames
|
||
|
*
|
||
|
* in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
|
||
|
* with the following flag, it will bypass `zone.js` patch for IE/Edge
|
||
|
*
|
||
|
* (window as any).__Zone_enable_cross_context_check = true;
|
||
|
*
|
||
|
*/
|
||
|
|
||
|
/***************************************************************************************************
|
||
|
* Zone JS is required by default for Angular itself.
|
||
|
*/
|
||
|
import 'zone.js'; // Included with Angular CLI.
|
||
|
|
||
|
/***************************************************************************************************
|
||
|
* APPLICATION IMPORTS
|
||
|
*/
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/assets/demo.css]" value="/* Component Communication cookbook specific styles */
|
||
|
.seconds {
|
||
|
background-color: black;
|
||
|
color: red;
|
||
|
font-size: 3em;
|
||
|
margin: 0.3em 0;
|
||
|
text-align: center;
|
||
|
width: 1.5em;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/styles.css]" value="/* Global Styles */
|
||
|
* {
|
||
|
font-family: Arial, Helvetica, sans-serif;
|
||
|
}
|
||
|
h1 {
|
||
|
color: #264D73;
|
||
|
font-size: 2.5rem;
|
||
|
}
|
||
|
h2, h3 {
|
||
|
color: #444;
|
||
|
font-weight: lighter;
|
||
|
}
|
||
|
h3 {
|
||
|
font-size: 1.3rem;
|
||
|
}
|
||
|
body {
|
||
|
padding: .5rem;
|
||
|
max-width: 1000px;
|
||
|
margin: auto;
|
||
|
}
|
||
|
@media (min-width: 600px) {
|
||
|
body {
|
||
|
padding: 2rem;
|
||
|
}
|
||
|
}
|
||
|
body, input[text] {
|
||
|
color: #333;
|
||
|
font-family: Cambria, Georgia, serif;
|
||
|
}
|
||
|
a {
|
||
|
cursor: pointer;
|
||
|
}
|
||
|
button {
|
||
|
background-color: #eee;
|
||
|
border: none;
|
||
|
border-radius: 4px;
|
||
|
cursor: pointer;
|
||
|
color: black;
|
||
|
font-size: 1.2rem;
|
||
|
padding: 1rem;
|
||
|
margin-right: 1rem;
|
||
|
margin-bottom: 1rem;
|
||
|
}
|
||
|
button:hover {
|
||
|
background-color: black;
|
||
|
color: white;
|
||
|
}
|
||
|
button:disabled {
|
||
|
background-color: #eee;
|
||
|
color: #aaa;
|
||
|
cursor: auto;
|
||
|
}
|
||
|
|
||
|
/* Navigation link styles */
|
||
|
nav a {
|
||
|
padding: 5px 10px;
|
||
|
text-decoration: none;
|
||
|
margin-right: 10px;
|
||
|
margin-top: 10px;
|
||
|
display: inline-block;
|
||
|
background-color: #e8e8e8;
|
||
|
color: #3d3d3d;
|
||
|
border-radius: 4px;
|
||
|
}
|
||
|
|
||
|
nav a:hover {
|
||
|
color: white;
|
||
|
background-color: #42545C;
|
||
|
}
|
||
|
nav a.active {
|
||
|
background-color: black;
|
||
|
color: white;
|
||
|
}
|
||
|
hr {
|
||
|
margin: 1.5rem 0;
|
||
|
}
|
||
|
input[type="text"] {
|
||
|
box-sizing: border-box;
|
||
|
width: 100%;
|
||
|
padding: .5rem;
|
||
|
}
|
||
|
|
||
|
|
||
|
/*
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
*/"><input type="hidden" name="files[src/app/app.component.html]" value="<h1 id="top">Component Communication Cookbook</h1>
|
||
|
|
||
|
<a href="#parent-to-child">Pass data from parent to child with input binding ("Heroes")</a><br/>
|
||
|
<a href="#parent-to-child-setter">Intercept input property changes with a setter ("Master")</a><br/>
|
||
|
<a href="#parent-to-child-on-changes">Intercept input property changes with <i>ngOnChanges</i> ("Source code version")</a><br/>
|
||
|
<a href="#child-to-parent">Parent listens for child event ("Colonize Universe")</a><br/>
|
||
|
<a href="#parent-to-child-local-var">Parent to child via <i>local variable</i>("Countdown to Liftoff")</a><br/>
|
||
|
<a href="#parent-to-view-child">Parent calls <i>ViewChild</i>("Countdown to Liftoff")</a><br/>
|
||
|
<a href="#bidirectional-service">Parent and children communicate via a service ("Mission Control")</a><br/>
|
||
|
|
||
|
<div id="parent-to-child">
|
||
|
<app-hero-parent></app-hero-parent>
|
||
|
</div>
|
||
|
<a href="#top" class="to-top">Back to Top</a>
|
||
|
|
||
|
<hr>
|
||
|
<div id="parent-to-child-setter">
|
||
|
<app-name-parent></app-name-parent>
|
||
|
</div>
|
||
|
<a href="#top" class="to-top">Back to Top</a>
|
||
|
|
||
|
<hr>
|
||
|
<div id="parent-to-child-on-changes">
|
||
|
<app-version-parent></app-version-parent>
|
||
|
</div>
|
||
|
<a href="#top" class="to-top">Back to Top</a>
|
||
|
|
||
|
<hr>
|
||
|
<div id="child-to-parent">
|
||
|
<app-vote-taker></app-vote-taker>
|
||
|
</div>
|
||
|
<a href="#top" class="to-top">Back to Top</a>
|
||
|
|
||
|
<hr>
|
||
|
<div id="parent-to-child-local-var">
|
||
|
<app-countdown-parent-lv></app-countdown-parent-lv>
|
||
|
</div>
|
||
|
<a href="#top" class="to-top">Back to Top</a>
|
||
|
|
||
|
<hr>
|
||
|
<div id="parent-to-view-child">
|
||
|
<app-countdown-parent-vc></app-countdown-parent-vc>
|
||
|
</div>
|
||
|
<a href="#top" class="to-top">Back to Top</a>
|
||
|
|
||
|
<hr>
|
||
|
<div id="bidirectional-service">
|
||
|
<app-mission-control></app-mission-control>
|
||
|
</div>
|
||
|
<a href="#top" class="to-top">Back to Top</a>
|
||
|
|
||
|
|
||
|
<!--
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
-->"><input type="hidden" name="files[src/index.html]" value="<!DOCTYPE html>
|
||
|
<html lang="en">
|
||
|
<head>
|
||
|
<meta charset="UTF-8">
|
||
|
<title>Passing information from parent to child</title>
|
||
|
<base href="/">
|
||
|
<style>
|
||
|
.to-top {margin-top: 8px; display: block;}
|
||
|
</style>
|
||
|
</head>
|
||
|
|
||
|
<body>
|
||
|
<app-root></app-root>
|
||
|
</body>
|
||
|
|
||
|
</html>
|
||
|
|
||
|
|
||
|
<!--
|
||
|
Copyright Google LLC. All Rights Reserved.
|
||
|
Use of this source code is governed by an MIT-style license that
|
||
|
can be found in the LICENSE file at https://angular.io/license
|
||
|
-->"><input type="hidden" name="files[angular.json]" value="{
|
||
|
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
|
||
|
"version": 1,
|
||
|
"newProjectRoot": "projects",
|
||
|
"projects": {
|
||
|
"angular.io-example": {
|
||
|
"projectType": "application",
|
||
|
"schematics": {
|
||
|
"@schematics/angular:application": {
|
||
|
"strict": true
|
||
|
}
|
||
|
},
|
||
|
"root": "",
|
||
|
"sourceRoot": "src",
|
||
|
"prefix": "app",
|
||
|
"architect": {
|
||
|
"build": {
|
||
|
"builder": "@angular-devkit/build-angular:browser",
|
||
|
"options": {
|
||
|
"outputPath": "dist",
|
||
|
"index": "src/index.html",
|
||
|
"main": "src/main.ts",
|
||
|
"polyfills": "src/polyfills.ts",
|
||
|
"tsConfig": "tsconfig.app.json",
|
||
|
"aot": true,
|
||
|
"assets": [
|
||
|
"src/favicon.ico",
|
||
|
"src/assets"
|
||
|
],
|
||
|
"styles": [
|
||
|
"src/styles.css"
|
||
|
],
|
||
|
"scripts": []
|
||
|
},
|
||
|
"configurations": {
|
||
|
"production": {
|
||
|
"fileReplacements": [
|
||
|
{
|
||
|
"replace": "src/environments/environment.ts",
|
||
|
"with": "src/environments/environment.prod.ts"
|
||
|
}
|
||
|
],
|
||
|
"optimization": true,
|
||
|
"outputHashing": "all",
|
||
|
"sourceMap": false,
|
||
|
"namedChunks": false,
|
||
|
"extractLicenses": true,
|
||
|
"vendorChunk": false,
|
||
|
"buildOptimizer": true,
|
||
|
"budgets": [
|
||
|
{
|
||
|
"type": "initial",
|
||
|
"maximumWarning": "500kb",
|
||
|
"maximumError": "1mb"
|
||
|
},
|
||
|
{
|
||
|
"type": "anyComponentStyle",
|
||
|
"maximumWarning": "2kb",
|
||
|
"maximumError": "4kb"
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"serve": {
|
||
|
"builder": "@angular-devkit/build-angular:dev-server",
|
||
|
"options": {
|
||
|
"browserTarget": "angular.io-example:build"
|
||
|
},
|
||
|
"configurations": {
|
||
|
"production": {
|
||
|
"browserTarget": "angular.io-example:build:production"
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"extract-i18n": {
|
||
|
"builder": "@angular-devkit/build-angular:extract-i18n",
|
||
|
"options": {
|
||
|
"browserTarget": "angular.io-example:build"
|
||
|
}
|
||
|
},
|
||
|
"test": {
|
||
|
"builder": "@angular-devkit/build-angular:karma",
|
||
|
"options": {
|
||
|
"main": "src/test.ts",
|
||
|
"polyfills": "src/polyfills.ts",
|
||
|
"tsConfig": "tsconfig.spec.json",
|
||
|
"karmaConfig": "karma.conf.js",
|
||
|
"assets": [
|
||
|
"src/favicon.ico",
|
||
|
"src/assets"
|
||
|
],
|
||
|
"styles": [
|
||
|
"src/styles.css"
|
||
|
],
|
||
|
"scripts": []
|
||
|
}
|
||
|
},
|
||
|
"lint": {
|
||
|
"builder": "@angular-devkit/build-angular:tslint",
|
||
|
"options": {
|
||
|
"tsConfig": [
|
||
|
"tsconfig.app.json",
|
||
|
"tsconfig.spec.json",
|
||
|
"e2e/tsconfig.json"
|
||
|
],
|
||
|
"exclude": [
|
||
|
"**/node_modules/**"
|
||
|
]
|
||
|
}
|
||
|
},
|
||
|
"e2e": {
|
||
|
"builder": "@angular-devkit/build-angular:protractor",
|
||
|
"options": {
|
||
|
"protractorConfig": "e2e/protractor.conf.js",
|
||
|
"devServerTarget": "angular.io-example:serve"
|
||
|
},
|
||
|
"configurations": {
|
||
|
"production": {
|
||
|
"devServerTarget": "angular.io-example:serve:production"
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
},
|
||
|
"defaultProject": "angular.io-example"
|
||
|
}
|
||
|
"><input type="hidden" name="files[tsconfig.json]" value="{
|
||
|
"compileOnSave": false,
|
||
|
"compilerOptions": {
|
||
|
"baseUrl": "./",
|
||
|
"outDir": "./dist/out-tsc",
|
||
|
"forceConsistentCasingInFileNames": true,
|
||
|
"noImplicitReturns": true,
|
||
|
"noFallthroughCasesInSwitch": true,
|
||
|
"sourceMap": true,
|
||
|
"declaration": false,
|
||
|
"downlevelIteration": true,
|
||
|
"experimentalDecorators": true,
|
||
|
"moduleResolution": "node",
|
||
|
"importHelpers": true,
|
||
|
"target": "es2015",
|
||
|
"module": "es2020",
|
||
|
"lib": [
|
||
|
"es2018",
|
||
|
"dom"
|
||
|
]
|
||
|
},
|
||
|
"angularCompilerOptions": {
|
||
|
"strictInjectionParameters": true,
|
||
|
"strictInputAccessModifiers": true,
|
||
|
"strictTemplates": true,
|
||
|
"enableIvy": true
|
||
|
}
|
||
|
}"><input type="hidden" name="tags[0]" value="angular"><input type="hidden" name="tags[1]" value="example"><input type="hidden" name="tags[2]" value="cookbook"><input type="hidden" name="tags[3]" value="component"><input type="hidden" name="description" value="Angular Example - Component Communication Cookbook samples"><input type="hidden" name="dependencies" value="{"@angular/animations":"~11.0.1","@angular/common":"~11.0.1","@angular/compiler":"~11.0.1","@angular/core":"~11.0.1","@angular/forms":"~11.0.1","@angular/platform-browser":"~11.0.1","@angular/platform-browser-dynamic":"~11.0.1","@angular/router":"~11.0.1","angular-in-memory-web-api":"~0.11.0","rxjs":"~6.6.0","tslib":"^2.0.0","zone.js":"~0.11.4","jasmine-core":"~3.6.0","jasmine-marbles":"~0.6.0"}"></form>
|
||
|
<script>
|
||
|
var embedded = 'ctl=1';
|
||
|
var isEmbedded = window.location.search.indexOf(embedded) > -1;
|
||
|
|
||
|
if (isEmbedded) {
|
||
|
var form = document.getElementById('mainForm');
|
||
|
var action = form.action;
|
||
|
var actionHasParams = action.indexOf('?') > -1;
|
||
|
var symbol = actionHasParams ? '&' : '?'
|
||
|
form.action = form.action + symbol + embedded;
|
||
|
}
|
||
|
document.getElementById("mainForm").submit();
|
||
|
</script>
|
||
|
</body></html>
|