0%

Angular 筆記 - 實作 API 的取得、刪除、新增、更新

angular

表單實作與 Angular 筆記 - FormArray 表單實作差不多,有些部分就不贅述,僅記錄 API 操作的部分。

資料

本次範例使用下方資料,已經建立成 db.json,並也啟用了 json-server

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
{
"posts": [
{
"name": "提姆",
"height": 175,
"id": 1
},
{
"id": 2,
"name": "lena",
"height": 160
},
{
"id": 3,
"name": "eda",
"height": 155
},
{
"id": 4,
"name": "mia",
"height": 170
}
]
}

建立 API 方法

  1. service 資料夾下建立一個 API 資料夾,裡面建立一個 data.service.ts
  2. 定義一個 options 為任意型別,並制定好 header 要接收的格式。
  3. mainUrl 的值是從 environment 中取得的,Angular 筆記 - Router 路由實作串接 API有提到過。
  4. 定義各種方法的 API,方法如註解所示。

data.service.ts

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
options: any;
mainUrl: string = environment.apiUrl;
constructor(private http: HttpClient) {
this.options = {
headers: new HttpHeaders({
'content-type': 'application/json',
}),
};
}

run() {
console.log('service run');
}

//*取得所有資料
getAllData(): Observable<PersonModal[]> {
return this.http.get<PersonModal[]>(`${this.mainUrl}/posts`);
}

//*取得單一資料
getData(): Observable<PersonModal[]> {
return this.http.get<PersonModal[]>(`${this.mainUrl}/posts/1`);
}

//*新增一筆資料
insertData(request: PersonModal) {
return this.http.post(`${this.mainUrl}/posts`, request, this.options);
}

//*更新一筆資料
updateData(request: PersonModal, id: number) {
return this.http.put(`${this.mainUrl}/posts/${id}`, request, this.options);
}

//*刪除一筆資料
deleteData(id: number) {
return this.http.delete(`${this.mainUrl}/posts/${id}`, this.options);
}

串接 API

先完成輸入框的部分,

html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<form [formGroup]="form">
<label>
<span>名稱:</span>
<input formControlName="name" type="text" />
</label>
<label>
<span>身高:</span>
<input formControlName="height" type="text" />
<span>cm</span>
</label>

<button type="button" class="btn btn-green" (click)="insertData()">
新增
</button>
<button type="button" class="btn btn-orange" (click)="submitData()">
修改
</button>
</form>

再把要呈現出清單的內容也寫出來,並把預設的欄位寫好。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<div class="title">
<h2>清單列表</h2>
</div>
<ul *ngFor="let item of lists">
<li>
<span> 名稱: {{ item.name }} </span>
<span> 身高:{{ item.height }}cm </span>

<button
class="btn btn-orange"
(click)="editData(item.id, item.name, item.height)"
>
編輯
</button>
<button class="btn btn-red" (click)="deleteData(item.id)">刪除</button>
</li>
</ul>

建立表單

建立表單的初始值。
list.component.ts

1
2
3
4
5
6
7
8
9
10
11
creatForm() {
this.form = this.formBuilder.group({
id: null,
name: ['', Validators.required],
height: ['', Validators.required],
});
// 觀察name輸入框的變數狀態
this.form.get('name').valueChanges.subscribe((res) => {
console.log('value:', res);
});
}

引入 AJAX 方法

data.service.ts 引入到建構式中。

1
2
3
4
constructor(
private formBuilder: FormBuilder,
private dataSvs: DataService
) {}

get 取得所有與單一資料

取得所有資料與取得單一資料的方法幾乎一樣,只是使用方法不同,詳細內容可以參照上方 data.service.ts 的內容。

取得所有資料
使用一個 getAllData 的方法把資料存起來,並且在 ngOnInit 時呼叫,把資料渲染在畫面上。

1
2
3
4
5
6
7
8
9
10
11
12

ngOnInit(): void {
this.creatForm();
this.getAllData();
}

getAllData() {
return this.dataSvs.getAllData().subscribe((res) => {
this.lists = res;
});
}
}

delete 刪除當筆資料

  1. 在顯示資料清單中,在每一筆資料後方新增一個刪除按鈕,並綁定一個點擊事件。
  2. 點擊後會刪除所觸發的那一筆資料,並從資料庫刪除。

list.component.html

因為要刪除該筆資料,所以在刪除方法中帶入該資料的 id,就可以把自己那筆資料刪除。

1
2
3
4
5
6
7
<ul *ngFor="let item of lists">
<li>
<span> 名稱: {{ item.name }} </span>
<span> 身高:{{ item.height }}cm </span>
<button class="btn btn-red" (click)="deleteData(item.id)">刪除</button>
</li>
</ul>

list.component.ts

刪除的方法帶入 id 參數,dataSvs 的刪除方法也接收到此 id 後,就會把該筆刪除,並重新呼叫 API。

1
2
3
4
5
6
7
//刪除一筆資料
deleteData(id) {
return this.dataSvs.deleteData(id).subscribe((res) => {
console.log(res);
this.getAllData();
});
}

post 新增資料

  1. 在輸入框輸入資料。
  2. 按下確認鍵後把輸入框的值傳給 db.json 中。

list.component.html

給予一個點擊事件按鈕,因為按鈕會預設為 submit,所以要給予 buttontypebutton,才不會因為按下 enter 就送出了。

1
<button type="button" class="btn btn-green" (click)="insertData()">新增</button>

list.component.ts

  1. 使用 dataSvs 寫好的 post 方法 inserData,並且把要傳送的物件格式寫在方法中。
  2. 傳送後重新呼叫 API 與清空表格。
1
2
3
4
5
6
7
8
9
10
11
insertData() {
this.dataSvs
.insertData({
name: this.form.value.name,
height: this.form.value.height,
})
.subscribe((res) => {
this.getAllData();
this.reset();
});
}

edit 編輯資料

這個方法與串接 API 方法無直接關係,但也滿值得紀錄一下。

list.component.html

與刪除方法類似,但這次要把有用到欄位用參數帶入 editData 方法中。

1
2
3
4
5
6
7
8
9
10
11
12
13
<ul *ngFor="let item of lists">
<li>
<span> 名稱: {{ item.name }} </span>
<span> 身高:{{ item.height }}cm </span>

<button
class="btn btn-orange"
(click)="editData(item.id, item.name, item.height)"
>
編輯
</button>
</li>
</ul>

list.component.ts

使用 form 本身的 patchValue 方法把欄位帶入對應屬性的值中。

1
2
3
4
5
6
7
editData(id: number, name: string, height: number) {
this.form.patchValue({
id: id,
name: name,
height: height,
});
}

put 更新檔案

  1. 這邊是編輯完後點擊 submitData 按鈕事件。
  2. 使用的是包裝後的 put 方法:updateData()

list.component.html

1
2
3
<button type="button" class="btn btn-orange" (click)="submitData()">
修改
</button>

list.component.ts

  1. 因為修改送出並不會取到該筆 id,所以另外在外面宣告一個 id 的變數,型別為 number
  2. id 變數儲存這個表單的 id
  3. 使用 dataSvs 中的 updateData 方法,並把要送出的物件格式放在參數的位置中,並給予對應的 id 欄位。
  4. 完成後重新呼叫 API 與清空輸入框。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
submitData() {
this.id = this.form.getRawValue().id;
this.dataSvs
.updateData(
{
name: this.form.value.name,
height: this.form.value.height,
},
this.id
)
.subscribe(() => {
this.getAllData();
this.reset();
});
}