學習如何在 Angular 串 API

Angular 是前端 framework,若要讀寫後端資料庫,就要靠 RESTful API 與後端溝通。

Version


Angular 4.3.3

任務說明


  • 實作全選功能
  • 實作刪除功能
  • 安裝 JSON Server
  • HTTP Request Method
  • 修改 JSON 資料
  • 設定 Angular Proxy
  • 注入 HttpClient
  • 使用 API

任務時間


  • 60 分鐘

實作全選功能


src/app.component.html

1
<input class="toggle-all" type="checkbox" (click)="toggleAll(toggleInput)" #toggleInput>

click event 綁定到 toggleAll(),並將 #toggleInput 傳入 toggleAll()

src/app.component.ts

1
2
3
4
5
6
7
toggleAll(toggleInput: HTMLInputElement) {
this.todos = this.todos.map(todo => {
todo.completed = toggleInput.checked;

return todo;
});
}

todo.completed 會跟據 toggleInput.checked 而改變,因此使用了 map(),將全部的 completed 根據 checked 改變。

實作刪除功能


src/app.component.html

1
<button class="destroy" (click)="removeTodo(todo.id)"></button>

click event 綁定到 removeTodo(),並將 todo.id 傳入 removeTodo()

src/app.component.ts

1
2
3
removeTodo(id: number) {
this.todos = this.todos.filter(todo => todo.id !== id);
}

將 id 刪除,也就是不等於此 id 則留下,相當於使用 filter()

安裝 JSON Server


使用 NPM 安裝

1
$ npm install -g json-server

將 JSON Server 安裝在 global 環境。

jsonserver000

啟動 JSON Server

1
2
3
4
~$ cd MyProject
~/MyProject$ mkdir json-server
~/MyProject$ cd json-server
~/MyProject/json-server$ json-server db.json
  1. 進入 MyProject 專案目錄
  2. 在專案目錄下建立 json-server 目錄
  3. 啟動 JSON Server,指定 db.json 為資料庫檔案

db.json 檔案存在,則 JSON Server 會以此檔案為資料庫,若不存在,則會建立新的 db.json 檔案。

jsonserver001

  1. 建立 json-server 目錄
  2. 進入 json-server 目錄
  3. json-server 目錄啟動 JSON Server,並將 db.json 檔案建立在 json-server 目錄下
  4. JSON Server 在 json-server 目錄下產生 db.json 檔案
  5. db.json 預設已經有預設資料了
  6. JSON Server 預設提供了網址可供測試

測試 JSON Server

預設 db.json 已經有資料,可藉此測試 JSON Server 是否有成功啟動。

1
http://localhost:3000/posts

jsonserver002

使用 Postman 測試 http://localhost:3000/posts,確定能抓到資料。

1
http://localhost:3000

jsonserver003

使用瀏覽器測試 http://localhost:3000,確定 JSON Server 內建 Web server 已經成功啟動。

JSON Server 支援開發中最常用的 GETPOSTPUTPATCHDELETE 等 request method。

HTTP Request Method


GET

用於取得 resource。

1
http://localhost:3000/posts

取得所有 post 資料。

jsonserver005

  1. 選擇 GET
  2. 輸入 http://localhost:3000/posts
  3. Send 送出 request
  4. 回傳 JSON 物件陣列
1
http://localhost:3000/posts/1

取得 id1post 資料。

jsonserver006

  1. 選擇 GET
  2. 輸入 http://localhost:3000/posts/1
  3. Send 送出 request
  4. 回傳 JSON 物件

POST

用於建立 resource。

1
http://localhost:3000/posts

建立新的一筆 post 資料。

jsonserver007

  1. 選擇 POST
  2. 輸入 http://localhost:3000/posts
  3. 選擇 Body
  4. 選擇 raw 格式
  5. 選擇 JSON (application/json) 格式
  6. 要新增的 JSON 物件
  7. Send 送出 request
  8. 回傳所新增的 JSON 物件,並包含 id

jsonserver008

  1. 開啟 /json-server/db.json
  2. 剛剛新增的 post 已經寫入 db.json

PUT

用於更新完整 resource。

1
http://localhost:3000/posts/2

更新 id2 的完整 post 資料。

jsonserver009

  1. 選擇 PUT
  2. 輸入 http://localhost:3000/posts/2
  3. 選擇 Body
  4. 選擇 raw 格式
  5. 選擇 JSON (application/json) 格式
  6. 要更新的 JSON 物件 (不用含 id,要包含全部欄位)
  7. Send 送出 request
  8. 回傳整筆 JSON 物件,並包含 id

jsonserver010

  1. 開啟 /json-server/db.json
  2. 剛剛更新的 post 已經寫入 db.json

使用 PUT 要小心,他是將整個 JSON 物件寫入原來的 id,也就是說原本有 3 個欄位,若 PUT 時的 JSON 物件只有 2 個欄位,則 PUT 後就只剩下 2 個欄位。

PATCH

用於更新部分 resource。

1
http://localhost:3000/posts/2

更新 id2 的部分 post 資料。

jsonserver011

  1. 選擇 PUT
  2. 輸入 http://localhost:3000/posts/2
  3. 選擇 Body
  4. 選擇 raw 格式
  5. 選擇 JSON (application/json) 格式
  6. 要更新的 JSON 物件 (不用含 id,不用包含全部欄位)
  7. Send 送出 request
  8. 回傳整筆 JSON 物件,並包含 id

jsonserver012

  1. 開啟 /json-server/db.json
  2. 剛剛更新的 post 已經寫入 db.json,且只更新 1 個欄位資料。

DELETE

用於刪除 resource。

1
http://localhost:3000/posts/2

jsonserver013

  1. 選擇 DELETE
  2. 輸入 http://localhost:3000/posts/2
  3. Send 送出 request
  4. 回傳空的 JSON 物件

jsonserver019

  1. 開啟 /json-server/db.json
  2. 剛剛更新的 post 資料已經被刪除。

建立假資料


JSON Server 並沒有搭配資料庫,因此也不需要 Sequel Pro 或 DataGrip 之類的工具連到資料庫,它只是個文字檔。

先建立一個 todos 的假資料。

/json-server/db.json

1
2
3
4
5
6
7
8
9
{
"todos": [
{
"id": 2,
"completed": false,
"value": "Study Angular"
}

]
}

假設已經有一筆 todo 在資料庫。

jsonserver020

  1. 開啟 /json-server/db.json
  2. 建立一筆 todo

設定 Route


JSON Server 預設是以 table 名稱作為 route,但實務上 API 的 route 可能不一樣,如 /api/todosapi/todos/1

json-server/routes.json

1
2
3
4
{
"/api/todos": "/todos",
"/api/todos/:id": "/todos/:id"
}

/api/todos 指向原本的 /todos

/api/todos/1 只像原本的 /todos/1

jsonserver021

  1. 新增 json-server/routes.json
  2. 編輯 routes 的對應規則

重新啟動 JSON Server


1
~/MyProject/json-server$ json-server db.json --routes routes.json

重新啟動 JSON Server,加上 —-routes 參數,指定套用 routes.json

設定 Angular Proxy


proxy.conf.json

1
2
3
4
5
6
{
"/api": {
"target": "http://localhost:3000",
"secure": false
}

}

建立 proxy.conf.json,指定 Angular 使用 /api 時,會導到 JSON Server。

jsonserver022

  1. 在專案根目錄新增 proxy.conf.json
  2. /api 導到 JSON Server 的 http://localhost:3000

修改 package.json


package.json

1
"start": "ng serve --proxy-config proxy.conf.json",

start 改成 ng serve --proxy-config proxy.conf.json

jsonserver023

  1. 編輯 package.json
  2. start 改成 ng serve --proxy-config proxy.conf.json

重新啟動 Angular


1
~/MyProject$ npm start

將原本使用 ng serve 啟動的 Angular 停止,改用 npm start 啟動 Angular。

jsonserver024

  1. 改用 npm start 啟動 Angular
  2. 實際上是執行 ng serve —proxy-config proxy.conf.json

注入 HttpClient


src/app.module.ts

1
2
3
4
imports: [
BrowserModule,
HttpClientModule,
],

加上 HttpClientModule

src/app.component.ts

1
2
constructor(private httpClient: HttpClient) {
}

使用 API


載入 Todo

src/app.component

1
2
3
4
5
6
ngOnInit(): void {
this.httpClient.get<Todo[]>('/api/todos')
.subscribe(
todos => this.todos = todos
);
}

使用 HttpClient.get()/api/todos 載入所有 todo,在 get() 之後要加上 <Todo[]> 泛型,表示想下載的資料型別為 Observable<Todo[]>

由於 HttpClient.get() 為 RxJS 的 Observable,所以必須加上 subscribe() 才會開始下載資料,並將 todos 陣列指定到 this.todos field。

新增 Todo

src/app.component

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
addTodo(newTodo: HTMLInputElement) {
const todo = {
id: this.todos.length + 1,
completed: false,
value: newTodo.value
};

this.httpClient.post('/api/todos', todo)
.subscribe();

this.httpClient.get<Todo[]>('/api/todos')
.subscribe(
todos => this.todos = todos
);

newTodo.value = '';
}

使用 HttpClient.post() 新增 todo 。

一樣使用 HttpClient.get() 將新增後的 todo 下載。

刪除 Todo

src/app.component

1
2
3
4
5
6
7
8
9
removeTodo(id: number) {
this.httpClient.delete(`/api/todos/${id}`)
.subscribe();

this.httpClient.get<Todo[]>('/api/todos')
.subscribe(
todos => this.todos = todos
);
}

使用 HttpClient.delete() 刪除 todo 。

一樣使用 HttpClient.get() 將新增後的 todo 下載。

Conclusion


  • JSON Server 讓我們不用安裝後端環境與資料庫,就能快速的建立假 API 開發測試。
  • Angular 4.3 的 HttpClient 提供了更方便的方式存取後端 API。
  • HttpClient 回傳的是 RxJS 的 observable,藉由 RxJS 豐富的 operator,我們可以快速的將 API 回傳的資料加工。
2017-08-06