docs: rewrite inputs/outputs section of Template Syntax (#27685)
PR Close #27685
This commit is contained in:

committed by
Andrew Kushnir

parent
e2fd628618
commit
f41242f18e
@ -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>
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
@ -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 */
|
||||
|
@ -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>
|
||||
|
@ -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!');
|
||||
}));
|
||||
});
|
55
aio/content/examples/inputs-outputs/src/app/app.component.ts
Normal file
55
aio/content/examples/inputs-outputs/src/app/app.component.ts
Normal 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
|
||||
|
28
aio/content/examples/inputs-outputs/src/app/app.module.ts
Normal file
28
aio/content/examples/inputs-outputs/src/app/app.module.ts
Normal 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 { }
|
@ -0,0 +1,3 @@
|
||||
<p>Latest clearance item: {{clearanceItem}}</p>
|
||||
|
||||
<button (click)="buyIt()"> Buy it with an Output!</button>
|
@ -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();
|
||||
});
|
||||
});
|
@ -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 */
|
@ -0,0 +1,2 @@
|
||||
<span [style.text-decoration]="lineThrough">Item: {{item}}</span>
|
||||
<button (click)="delete()">Delete it with an Output!</button>
|
@ -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();
|
||||
});
|
||||
});
|
@ -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
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
<h2>Child component with @Input()</h2>
|
||||
|
||||
<!-- #docregion property-in-template -->
|
||||
<p>
|
||||
Today's item: {{item}}
|
||||
</p>
|
||||
<!-- #enddocregion property-in-template -->
|
||||
|
@ -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();
|
||||
});
|
||||
});
|
@ -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
|
@ -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 -->
|
@ -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();
|
||||
});
|
||||
});
|
@ -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
|
Reference in New Issue
Block a user