0%

Angular 筆記 - input 與 output

angular

inputoutput 顧名思義就是進入與輸出,是使用在父子層傳遞資料使用,馬上來看練習。

父層與子層

目前我有兩個資料夾,父層為 main,子層為 main-child

main

父層 main.component

main.componemt.html

1
2
3
4
<h2>This is Main</h2>
<p>My name is {{ person.name }}</p>
<p>My height is {{ person.height }}cm</p>
<input type="text" [(ngModel)]="text" />

main.componemt.ts

1
2
3
4
5
6
person: = {
name: 'Tim',
height: 175,
weight: 78,
};
text:string = 'Tim'

可以理解畫面會呈現物件中的資料。

mainView

子層 main-child.component

main-child.component.html

在子層新增以下標籤與事件,

1
2
3
<h2>This is main-child</h2>
<button (click)="callDad()">這是子層的按鈕</button>
<button (click)="changeText()">會更改文字按鈕</button>

main-child.component.ts
在 ts 增加事件。

1
2
3
4
5
6
callDad() {
alert('事件傳送到父層了,按下確定會更改外層身高');
}
changeText() {
alert('事件傳送到父層了,按下確定會更改外層文字');
}

讓子層資料引入父層

把子層 html 的 component 引入父層中,這樣才會正確顯示。

1
2
3
4
5
<h2>This is Main</h2>
<p>My name is {{ person.name }}</p>
<p>My height is {{ person.height }}cm</p>
<app-main-child></app-main-child>
<input type="text" [(ngModel)]="text" />

這時候畫面會顯示如下,

all

點擊按鈕會出現預設的警示視窗。

alert

將子層的資料傳給父層

因為要先讓子層接收父層的資料,所以要在子層的 template 使用屬性繫結的指令把父層綁定其上。

main.component

1
2
3
4
5
<h2>This is Main</h2>
<p>My name is {{ person.name }}</p>
<p>My height is {{ person.height }}cm</p>

<app-main-child [parentName]="person.name"></app-main-child>
  1. 在到子層的 ts 檔案使用 @Input() 接收父層資料,記得 Input 的開頭要大寫,且是一個方法,接收類型是 string。
  2. 方法後面接著屬性繫結的自訂義名稱
    main-child.component.ts
1
@Input() parentName: string;

透過子層事件把父層資料修改

既然有 input 就有 output,新增兩個事件,

  1. 按下按鈕修改名字。
  2. 按下按鈕修改身高數值。

使用 @Output() 方法,並給予自訂事件名稱,並 new 一個 EventEmitter() 的發射器。
在先前的事件中加入要傳出去的事件,使用 emit() 方法,括號裡面帶入要傳出去的值。

1
2
3
4
5
6
7
8
9
10
11
@Output() pushToFather = new EventEmitter();
@Output() pushTextToFather = new EventEmitter();

callDad() {
alert('事件傳送到父層了,按下確定會更改外層身高');
this.pushToFather.emit(170);//更改身高
}
changeText() {
alert('事件傳送到父層了,按下確定會更改外層文字');
this.pushTextToFather.emit('提姆');//更改名稱
}

父層要接收子層的資料

在父層的子層標籤中要再加入接口的事件,並且在事件中要加入 $event 參數,才能把資料傳到父層。

main.component.html

1
2
3
4
5
<app-main-child
[parentName]="person.name"
(pushToFather)="getChild($event)"
(pushTextToFather)="getChildText($event)"
></app-main-child>

可以看到子層的 template 已經有接收父層的事件,而事件名與子層的傳出來的名稱相同,在後面要在父層中加上父層要接收的方法。

main.component.ts

1
2
3
4
5
6
7
8
9
getChild(height: number) {
this.person.height = height;
}
getChildText(name: string) {
this.text = name;
}
getInput(input) {
console.log(input);
}

這時候可能會發現有錯誤訊息,EventEmitter 發射器的引入位置錯誤,應該是要從 @angular/core 引入,所以就把這個方法貼到引入位置為 @angular/core 的大括號內。

1
import { Component, OnInit, EventEmitter, Input, Output } from "@angular/core";

這樣就完成了父子層傳遞資料的方法,完整程式碼可以看 Demo