/* tslint:disable:forin */
import { Component, ContentChildren, Directive, EventEmitter,
Injectable, Input, Output, Optional,
HostBinding, HostListener,
OnInit, OnChanges, OnDestroy,
Pipe, PipeTransform,
SimpleChange } from '@angular/core';
import { of } from 'rxjs';
import { delay } from 'rxjs/operators';
////////// The App: Services and Components for the tests. //////////////
export class Hero {
name: string;
}
////////// Services ///////////////
// #docregion ValueService
@Injectable()
export class ValueService {
protected value = 'real value';
getValue() { return this.value; }
setValue(value: string) { this.value = value; }
getObservableValue() { return of('observable value'); }
getPromiseValue() { return Promise.resolve('promise value'); }
getObservableDelayValue() {
return of('observable delay value').pipe(delay(10));
}
}
// #enddocregion ValueService
// #docregion MasterService
@Injectable()
export class MasterService {
constructor(private masterService: ValueService) { }
getValue() { return this.masterService.getValue(); }
}
// #enddocregion MasterService
/////////// Pipe ////////////////
/*
* Reverse the input string.
*/
// #docregion ReversePipe
@Pipe({ name: 'reverse' })
export class ReversePipe implements PipeTransform {
transform(s: string) {
let r = '';
for (let i = s.length; i; ) { r += s[--i]; };
return r;
}
}
// #enddocregion ReversePipe
//////////// Components /////////////
@Component({
selector: 'bank-account',
template: `
Bank Name: {{bank}}
Account Id: {{id}}
`
})
export class BankAccountComponent {
@Input() bank: string;
@Input('account') id: string;
// Removed on 12/02/2016 when ceased public discussion of the `Renderer`. Revive in future?
// constructor(private renderer: Renderer, private el: ElementRef ) {
// renderer.setElementProperty(el.nativeElement, 'customProperty', true);
// }
}
/** A component with attributes, styles, classes, and property setting */
@Component({
selector: 'bank-account-parent',
template: `
`
})
export class BankAccountParentComponent {
width = 200;
color = 'red';
isClosed = true;
}
// #docregion LightswitchComp
@Component({
selector: 'lightswitch-comp',
template: `
{{message}}`
})
export class LightswitchComponent {
isOn = false;
clicked() { this.isOn = !this.isOn; }
get message() { return `The light is ${this.isOn ? 'On' : 'Off'}`; }
}
// #enddocregion LightswitchComp
@Component({
selector: 'child-1',
template: `Child-1({{text}})`
})
export class Child1Component {
@Input() text = 'Original';
}
@Component({
selector: 'child-2',
template: '
Child-2({{text}})
'
})
export class Child2Component {
@Input() text: string;
}
@Component({
selector: 'child-3',
template: 'Child-3({{text}})
'
})
export class Child3Component {
@Input() text: string;
}
@Component({
selector: 'input-comp',
template: ``
})
export class InputComponent {
name = 'John';
}
/* Prefer this metadata syntax */
// @Directive({
// selector: 'input[value]',
// host: {
// '[value]': 'value',
// '(input)': 'valueChange.emit($event.target.value)'
// },
// inputs: ['value'],
// outputs: ['valueChange']
// })
// export class InputValueBinderDirective {
// value: any;
// valueChange: EventEmitter = new EventEmitter();
// }
// As the styleguide recommends
@Directive({ selector: 'input[value]' })
export class InputValueBinderDirective {
@HostBinding()
@Input()
value: any;
@Output()
valueChange: EventEmitter = new EventEmitter();
@HostListener('input', ['$event.target.value'])
onInput(value: any) { this.valueChange.emit(value); }
}
@Component({
selector: 'input-value-comp',
template: `
Name: {{name}}
`
})
export class InputValueBinderComponent {
name = 'Sally'; // initial value
}
@Component({
selector: 'parent-comp',
template: `Parent()`
})
export class ParentComponent { }
@Component({
selector: 'io-comp',
template: `Original {{hero.name}}
`
})
export class IoComponent {
@Input() hero: Hero;
@Output() selected = new EventEmitter();
click() { this.selected.emit(this.hero); }
}
@Component({
selector: 'io-parent-comp',
template: `
Click to select a hero
The selected hero is {{selectedHero.name}}
`
})
export class IoParentComponent {
heroes: Hero[] = [ {name: 'Bob'}, {name: 'Carol'}, {name: 'Ted'}, {name: 'Alice'} ];
selectedHero: Hero;
onSelect(hero: Hero) { this.selectedHero = hero; }
}
@Component({
selector: 'my-if-comp',
template: `MyIf(More)`
})
export class MyIfComponent {
showMore = false;
}
@Component({
selector: 'my-service-comp',
template: `injected value: {{valueService.value}}`,
providers: [ValueService]
})
export class TestProvidersComponent {
constructor(public valueService: ValueService) {}
}
@Component({
selector: 'my-service-comp',
template: `injected value: {{valueService.value}}`,
viewProviders: [ValueService]
})
export class TestViewProvidersComponent {
constructor(public valueService: ValueService) {}
}
@Component({
selector: 'external-template-comp',
templateUrl: './demo-external-template.html'
})
export class ExternalTemplateComponent implements OnInit {
serviceValue: string;
constructor(@Optional() private service: ValueService) { }
ngOnInit() {
if (this.service) { this.serviceValue = this.service.getValue(); }
}
}
@Component({
selector: 'comp-w-ext-comp',
template: `
comp-w-ext-comp
`
})
export class InnerCompWithExternalTemplateComponent { }
@Component({selector: 'needs-content', template: ''})
export class NeedsContentComponent {
// children with #content local variable
@ContentChildren('content') children: any;
}
///////// MyIfChildComp ////////
@Component({
selector: 'my-if-child-1',
template: `
MyIfChildComp
Change log:
{{i + 1}} - {{log}}
`
})
export class MyIfChildComponent implements OnInit, OnChanges, OnDestroy {
@Input() value = '';
@Output() valueChange = new EventEmitter();
get childValue() { return this.value; }
set childValue(v: string) {
if (this.value === v) { return; }
this.value = v;
this.valueChange.emit(v);
}
changeLog: string[] = [];
ngOnInitCalled = false;
ngOnChangesCounter = 0;
ngOnDestroyCalled = false;
ngOnInit() {
this.ngOnInitCalled = true;
this.changeLog.push('ngOnInit called');
}
ngOnDestroy() {
this.ngOnDestroyCalled = true;
this.changeLog.push('ngOnDestroy called');
}
ngOnChanges(changes: {[propertyName: string]: SimpleChange}) {
for (let propName in changes) {
this.ngOnChangesCounter += 1;
let prop = changes[propName];
let cur = JSON.stringify(prop.currentValue);
let prev = JSON.stringify(prop.previousValue);
this.changeLog.push(`${propName}: currentValue = ${cur}, previousValue = ${prev}`);
}
}
}
///////// MyIfParentComp ////////
@Component({
selector: 'my-if-parent-comp',
template: `
MyIfParentComp
`
})
export class MyIfParentComponent implements OnInit {
ngOnInitCalled = false;
parentValue = 'Hello, World';
showChild = false;
toggleLabel = 'Unknown';
ngOnInit() {
this.ngOnInitCalled = true;
this.clicked();
}
clicked() {
this.showChild = !this.showChild;
this.toggleLabel = this.showChild ? 'Close' : 'Show';
}
}
@Component({
selector: 'reverse-pipe-comp',
template: `
{{text | reverse}}
`
})
export class ReversePipeComponent {
text = 'my dog has fleas.';
}
@Component({template: 'Replace Me
'})
export class ShellComponent { }
@Component({
selector: 'demo-comp',
template: `
Specs Demo
Input/Output Component
External Template Component
Component With External Template Component
Reverse Pipe
InputValueBinder Directive
Button Component
Needs Content
!
`
})
export class DemoComponent { }
//////// Aggregations ////////////
export const demoDeclarations = [
DemoComponent,
BankAccountComponent, BankAccountParentComponent,
LightswitchComponent,
Child1Component, Child2Component, Child3Component,
ExternalTemplateComponent, InnerCompWithExternalTemplateComponent,
InputComponent,
InputValueBinderDirective, InputValueBinderComponent,
IoComponent, IoParentComponent,
MyIfComponent, MyIfChildComponent, MyIfParentComponent,
NeedsContentComponent, ParentComponent,
TestProvidersComponent, TestViewProvidersComponent,
ReversePipe, ReversePipeComponent, ShellComponent
];
export const demoProviders = [MasterService, ValueService];
////////////////////
////////////
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { FormsModule } from '@angular/forms';
@NgModule({
imports: [BrowserModule, FormsModule],
declarations: demoDeclarations,
providers: demoProviders,
entryComponents: [DemoComponent],
bootstrap: [DemoComponent]
})
export class DemoModule { }