ようやく触り始めてるAngular2です。Angular2に定義されている@Input
と@Output
について触ってみている、ぱっと見キモい。どんな振る舞いをしているのかイマイチわからないのでメモ程度に備忘します。@Input
と@Output
は梱包しているComponentと梱包されているComponent(ダジャレではない)の関係をまず定義する必要があります。
@Input
も@Output
も梱包されているdetail-app
へ定義する
@Input
は「my-app」から属性経由で値を「detail-app」が受け取るパターン@Output
は「detail-app」から「my-app」へイベントを送るパターン
@Input
が扱うのは文字列で@Output
はイベント通知できるPrimise的なもので、でないと「Uncaught (in promise): TypeError: this.directive_1_0.hoge.subscribe is not a function」というエラーを投げる。
具体的には One framework. - Angular 2 にあるサンプルを見るとだいたい分かる。
@Input サンプル
「my-app」に「detail-app」を定義し、bank-name
とaccount-id
の値を入れる。それをコンポーネント「detail-app」に渡す。
具体的には次の通り:
(my-app)
@Component({ selector: 'my-app', template: ` <detail-app bank-name="RBC" account-id="4747"></detail-app> `, directives: [DetailApp] })
受け取る「detail-app」は次のように定義する。
(detail-app)
@Component({ selector: 'detail-app', template: ` <div>Bank Name: {{bankName}}</div> <div>Account Id: {{id}}</div> <div>normalizedBankName: {{normalizedBankName}}</div> ` }) class DetailApp { @Input('bank-name') bankName: string; @Input('account-id') id: string; normalizedBankName: string; constructor() { this.normalizedBankName = 'ほげ' } }
通常「{{}}」で値を表示する場合はnormalizedBankName
のように使うが@Input
を使って属性で定義された値を取得できる。
@Input('bank-name') bankName: string;
について、@Input(…)内で定義されているのがカスタムタグで定義したときの属性の書き方(つまり<detail-app bank-name="RBC">
)で、その隣の「bankName: string」がコンポーネントで利用するときの変数(つまり<div>Bank Name: {{bankName}}</div>
)になる。
@Output サンプル
「my-app」に「detail-app」を定義し「detail-app」に発火用イベントを定義する。発火したイベントの具体的な処理を「my-app」に書く。
具体的には
(my-app)
@Component({ selector: 'my-app', template: ` <detail-app (everySecond)="everySecond()" (everyFiveSeconds)="everyFiveSeconds()"></detail-app> `, directives: [DetailApp] }) class App { everySecond() { console.log('second'); } everyFiveSeconds() { console.log('five seconds'); } }
イベント発火させる「detail-app」は次のように定義する。
(detail-app)
@Directive({ selector: 'detail-app' }) class DetailApp { @Output() everySecond = new EventEmitter(); @Output('everyFiveSeconds') five5Secs = new EventEmitter(); constructor() { setInterval(() => this.everySecond.emit("event"), 1000); setInterval(() => this.five5Secs.emit("event"), 5000); } }
参考資料
参考資料はこちら
@Directive と @Component の使い分け
@Component
はtemplate必須で@Directive
はtemplate必須で無い。@Component
はtemplateを梱包する場合に利用する(ので通常の利用方法)。今回の@Output
サンプルのようにテンプレートを利用しない場合は@Directive
で良い。なので上記@Directive
のサンプルは@Component
を使って
@Component({ selector: 'detail-app', template: `` }) class DetailApp { @Output() everySecond = new EventEmitter(); @Output('everyFiveSeconds') five5Secs = new EventEmitter(); constructor() { setInterval(() => this.everySecond.emit("event"), 1000); setInterval(() => this.five5Secs.emit("event"), 5000); } }
とも書ける
@Inputの書き方注意
足し算の注意で型をnumberにしたからっていいものではない。
@Component({ selector: 'detail-app', template: ` <div>Bank Name: {{bankNum+1}}</div> ` }) class DetailApp { @Input('bank-number') bankNum: number; }
「detail-app」タグを書くときには次のように[bank-number]
とする必要がある
@Component({ selector: 'my-app', template: ` <detail-app [bank-number]="12"></detail-app> `, directives: [DetailApp] })
@Inputと@Outputは@無しでも
@Input
と@Output
は@無しでも書けます。つまり
(detail-app)
@Component({ selector: 'detail-app', template: ` <div>Bank Name: {{bankNumber+1}}</div> `, inputs: ['bankNumber: bank-number'] }) class DetailApp { bankNumber: number; }
ただこの書き方は「Angular2 Style Guilde」ではよろしくないということです、よろしく。
おわり