docs: rewrite inputs/outputs section of Template Syntax (#27685)

PR Close #27685
This commit is contained in:
Kapunahele Wong
2018-12-03 13:42:53 -05:00
committed by Andrew Kushnir
parent e2fd628618
commit f41242f18e
35 changed files with 875 additions and 128 deletions

View File

@ -0,0 +1,7 @@
<p>Save for later item: {{input1}}</p>
<button (click)="saveIt()"> Save for later</button>
<p>Item for wishlist: {{input2}}</p>
<button (click)="wishForIt()"> Add to wishlist</button>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { AliasingComponent } from './aliasing.component';
describe('AliasingComponent', () => {
let component: AliasingComponent;
let fixture: ComponentFixture<AliasingComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ AliasingComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(AliasingComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,46 @@
/* tslint:disable:use-input-property-decorator */
/* tslint:disable:use-output-property-decorator */
/* tslint:disable:no-input-rename */
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-aliasing',
templateUrl: './aliasing.component.html',
styleUrls: ['./aliasing.component.css'],
// #docregion alias
// tslint:disable: no-inputs-metadata-property no-outputs-metadata-property
inputs: ['input1: saveForLaterItem'], // propertyName:alias
outputs: ['outputEvent1: saveForLaterEvent']
// tslint:disable: no-inputs-metadata-property no-outputs-metadata-property
// #enddocregion alias
})
export class AliasingComponent {
input1: string;
outputEvent1: EventEmitter<string> = new EventEmitter<string>();
// #docregion alias-input-output
@Input('wishListItem') input2: string; // @Input(alias)
@Output('wishEvent') outputEvent2 = new EventEmitter<string>(); // @Output(alias) propertyName = ...
// #enddocregion alias-input-output
saveIt() {
console.warn('Child says: emiting outputEvent1 with', this.input1);
this.outputEvent1.emit(this.input1);
}
wishForIt() {
console.warn('Child says: emiting outputEvent2', this.input2);
this.outputEvent2.emit(this.input2);
}
}
/* tslint:enable:use-input-property-decorator */
/* tslint:enable:use-output-property-decorator */

View File

@ -0,0 +1,45 @@
<h1>Inputs and Outputs</h1>
<!-- #docregion input-parent -->
<app-item-detail [item]="currentItem"></app-item-detail>
<!-- #enddocregion input-parent -->
<hr>
<!-- #docregion output-parent -->
<app-item-output (newItemEvent)="addItem($event)"></app-item-output>
<!-- #enddocregion output-parent -->
<h3>Parent component receiving value via @Output()</h3>
<ul>
<li *ngFor="let item of items">{{item}}</li>
</ul>
<hr>
<h2>Input and Output together</h2>
<p>Open the console to see the EventEmitter at work when you click Delete.</p>
<!-- #docregion together -->
<app-input-output [item]="currentItem" (deleteRequest)="crossOffItem($event)"></app-input-output>
<!-- #enddocregion together -->
<hr>
<h2>Input and Output in the component class metadata</h2>
<p>Open the console to see the EventEmitter at work when you click Buy.</p>
<app-in-the-metadata [clearanceItem]="lastChanceItem" (buyEvent)="buyClearanceItem($event)"></app-in-the-metadata>
<hr>
<h2>Aliasing Inputs and Outputs</h2>
<p>See aliasing.component.ts for aliases and the console for the EventEmitter console logs.</p>
<app-aliasing [saveForLaterItem]="currentItem" (saveForLaterEvent)="saveForLater($event)" [wishListItem]="currentItem" (wishEvent)="addToWishList($event)"></app-aliasing>
<h2>Wishlist:</h2>
<ul>
<li *ngFor="let wish of wishlist">{{wish}}</li>
</ul>

View File

@ -0,0 +1,27 @@
import { TestBed, async } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [
AppComponent
],
}).compileComponents();
}));
it('should create the app', async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app).toBeTruthy();
}));
it(`should have as title 'app'`, async(() => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.debugElement.componentInstance;
expect(app.title).toEqual('app');
}));
it('should render title in a h1 tag', async(() => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.debugElement.nativeElement;
expect(compiled.querySelector('h1').textContent).toContain('Welcome to app!');
}));
});

View File

@ -0,0 +1,55 @@
// #docplaster
import { Component } from '@angular/core';
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css']
})
// #docregion parent-property
// #docregion add-new-item
export class AppComponent {
// #enddocregion add-new-item
currentItem = 'Television';
// #enddocregion parent-property
lastChanceItem = 'Beanbag';
// #docregion add-new-item
items = ['item1', 'item2', 'item3', 'item4'];
// #enddocregion add-new-item
wishlist = ['Drone', 'Computer'];
// #docregion add-new-item
addItem(newItem: string) {
this.items.push(newItem);
}
// #enddocregion add-new-item
crossOffItem(item: string) {
console.warn(`Parent says: crossing off ${item}.`);
}
buyClearanceItem(item) {
console.warn(`Parent says: buying ${item}.`);
}
saveForLater(item) {
console.warn(`Parent says: saving ${item} for later.`);
}
addToWishList(wish: string) {
console.warn(`Parent says: adding ${this.currentItem} to your wishlist.`);
this.wishlist.push(wish);
console.warn(this.wishlist);
}
// #docregion add-new-item
// #docregion parent-property
}
// #enddocregion add-new-item
// #enddocregion parent-property

View File

@ -0,0 +1,28 @@
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';
import { ItemDetailComponent } from './item-detail/item-detail.component';
import { ItemOutputComponent } from './item-output/item-output.component';
import { InputOutputComponent } from './input-output/input-output.component';
import { InTheMetadataComponent } from './in-the-metadata/in-the-metadata.component';
import { AliasingComponent } from './aliasing/aliasing.component';
@NgModule({
declarations: [
AppComponent,
ItemDetailComponent,
ItemOutputComponent,
InputOutputComponent,
InTheMetadataComponent,
AliasingComponent
],
imports: [
BrowserModule
],
providers: [],
bootstrap: [AppComponent]
})
export class AppModule { }

View File

@ -0,0 +1,3 @@
<p>Latest clearance item: {{clearanceItem}}</p>
<button (click)="buyIt()"> Buy it with an Output!</button>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { InTheMetadataComponent } from './in-the-metadata.component';
describe('InTheMetadataComponent', () => {
let component: InTheMetadataComponent;
let fixture: ComponentFixture<InTheMetadataComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ InTheMetadataComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(InTheMetadataComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,32 @@
/* tslint:disable:use-input-property-decorator */
/* tslint:disable:use-output-property-decorator */
import { Component, EventEmitter, Input, Output } from '@angular/core';
@Component({
selector: 'app-in-the-metadata',
templateUrl: './in-the-metadata.component.html',
styleUrls: ['./in-the-metadata.component.css'],
// #docregion metadata
// tslint:disable: no-inputs-metadata-property no-outputs-metadata-property
inputs: ['clearanceItem'],
outputs: ['buyEvent']
// tslint:enable: no-inputs-metadata-property no-outputs-metadata-property
// #enddocregion metadata
})
export class InTheMetadataComponent {
buyEvent = new EventEmitter<string>();
clearanceItem: string;
buyIt() {
console.warn('Child says: emiting buyEvent with', this.clearanceItem);
this.buyEvent.emit(this.clearanceItem);
}
}
/* tslint:enable:use-input-property-decorator */
/* tslint:enable:use-output-property-decorator */

View File

@ -0,0 +1,2 @@
<span [style.text-decoration]="lineThrough">Item: {{item}}</span>
<button (click)="delete()">Delete it with an Output!</button>

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { InputOutputComponent } from './input-output.component';
describe('InputOutputComponent', () => {
let component: InputOutputComponent;
let fixture: ComponentFixture<InputOutputComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ InputOutputComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(InputOutputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,25 @@
import { Component, Input, Output, EventEmitter } from '@angular/core';
@Component({
selector: 'app-input-output',
templateUrl: './input-output.component.html',
styleUrls: ['./input-output.component.css']
})
export class InputOutputComponent {
// #docregion input-output
@Input() item: string;
// #docregion output
@Output() deleteRequest = new EventEmitter<string>();
// #enddocregion output
// #enddocregion input-output
lineThrough = '';
// #docregion delete-method
delete() {
console.warn('Child says: emiting item deleteRequest with', this.item);
this.deleteRequest.emit(this.item);
this.lineThrough = this.lineThrough ? '' : 'line-through';
}
// #enddocregion delete-method
}

View File

@ -0,0 +1,8 @@
<h2>Child component with @Input()</h2>
<!-- #docregion property-in-template -->
<p>
Today's item: {{item}}
</p>
<!-- #enddocregion property-in-template -->

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemDetailComponent } from './item-detail.component';
describe('ItemDetailComponent', () => {
let component: ItemDetailComponent;
let fixture: ComponentFixture<ItemDetailComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ItemDetailComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ItemDetailComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,16 @@
// #docplaster
// #docregion use-input
import { Component, Input } from '@angular/core'; // First, import Input
// #enddocregion use-input
@Component({
selector: 'app-item-detail',
templateUrl: './item-detail.component.html',
styleUrls: ['./item-detail.component.css']
})
// #docregion use-input
export class ItemDetailComponent {
@Input() item: string; // decorate the property with @Input()
}
// #enddocregion use-input

View File

@ -0,0 +1,6 @@
<h2>Child component with @Output()</h2>
<!-- #docregion child-output -->
<label>Add an item: <input #newItem></label>
<button (click)="addNewItem(newItem.value)">Add to parent's list</button>
<!-- #enddocregion child-output -->

View File

@ -0,0 +1,25 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ItemOutputComponent } from './item-output.component';
describe('ItemOutputComponent', () => {
let component: ItemOutputComponent;
let fixture: ComponentFixture<ItemOutputComponent>;
beforeEach(async(() => {
TestBed.configureTestingModule({
declarations: [ ItemOutputComponent ]
})
.compileComponents();
}));
beforeEach(() => {
fixture = TestBed.createComponent(ItemOutputComponent);
component = fixture.componentInstance;
fixture.detectChanges();
});
it('should create', () => {
expect(component).toBeTruthy();
});
});

View File

@ -0,0 +1,22 @@
// #docregion imports
import { Component, Output, EventEmitter } from '@angular/core';
// #enddocregion imports
@Component({
selector: 'app-item-output',
templateUrl: './item-output.component.html',
styleUrls: ['./item-output.component.css']
})
// #docregion item-output-class
export class ItemOutputComponent {
// #docregion item-output
@Output() newItemEvent = new EventEmitter<string>();
// #enddocregion item-output
addNewItem(value: string) {
this.newItemEvent.emit(value);
}
}
// #enddocregion item-output-class