iT邦幫忙

2019 iT 邦幫忙鐵人賽

DAY 6
6
Modern Web

Angular 深入淺出三十天系列 第 6

[Angular 深入淺出三十天] Day 05 - Angular 小學堂(一)

  • 分享至 

  • xImage
  •  

「接下來要說明的是...喂!睡著了阿你?!」專心講解的我瞄了 Wayne 一眼,才發現這小子居然已經睡倒流口水了?!

「對不起!!因為一直在講解沒有實作,一不小心就睡著了...。」Wayne 被我拍了一下醒了過來,擦了擦嘴邊的口水後,不好意思地說道。

「好吧!既然如此,我們寫些小功能來提振一下精神好了!」又好氣又好笑的我見狀只好決定先做個小功能來暖暖身,順便為後面的講解鋪個路。

「Finally!!事不宜遲,我們趕快開始吧!!」聽到終於可以開始實作的消息之後,Wayne 高舉雙手並開心地說道。

「首先,用 VSCode 開啟我們剛剛用 Angular CLI 建立出來的 HelloAngular 專案...」


初次見面

Imgur

還記得這個畫面嗎?這是我們在第三天的時候,將用 Angular CLI 建立出來的專案,並且一樣用 Angular CLI 令其啟動之後,在 localhost:4200 上會看到的畫面 。(如果忘記怎麼啟動的話,趕快到點我複習一下!)

接著用 VSCode 開啟我們的 HelloAngular 專案(不知道怎麼開啟的話可以參考這篇文章,容我小小地偷懶一下!),應該會看到類似這樣子的畫面:

Imgur

打開 app.component.html 這個檔案:

Imgur

沒錯!仔細一看你會發現,這就是啟動之後的那個畫面的 HTML。但除了 base64String 型態的圖片之外,應該還有個地方會讓你有點在意:

Imgur

咦?!這個 {{ }} 符號好特別阿?!

沒錯!這是 Angular 用來綁定資料的其中一種方式─插值表達式,將要綁定的資料變數放在 {{ }} 裡面,Angular 就知道在這裡要將變數裡的資料放進去。

接著打開 app.component.ts 這個檔案:

Imgur

這個檔案只有短短 10 行,且有個名為 title 的變數:

Imgur

沒錯,這就是上述有提到的,Angular 將 title 這個變數裡的資料,放進了在 Template 中的 {{ title }} 位置裡,所以瀏覽器的畫面才有 Welcome to app! 的字樣。

如果想將其改為 Welcome to my first Angular App! 呢?試試看吧!


初次應用

接著我們做個難一點點的練習,這次利用臺北市政府資料開放平台臺北捷運列車到站站名資料,來做個「臺北捷運列車到站站名列表」好了!成果大概會長這樣:

Imgur

這次的練習除了會用到上述提到的插值表達式- {{ }} 之外,還可以練習使用結構型指令-*ngFor 以及管道 (pipe)date。 準備好了嗎?開始囉!

讓我們重新建立一個新專案(要用 HelloAngular 專案當然也是可以):

ng new MRTStationList

再根據臺北市政府資料開放平台的敘述找到我們需要資訊:

Imgur

然後開啟從臺北市政府資料開放平台下載的資料(如果開啟時發現是亂碼請莫急莫慌莫害怕,該資料是 Big-5 的編碼格式,稍微調整一下即可。點我看教學),並找個線上的格式美化器如 JSON Viewer 來美化一下資料格式,比較容易看得懂:

Imgur

接著用 VSCode 開啟剛剛建立的 MRTStationList 專案,將 app.component.html 裡的 HTML 全刪掉,替換成以下內容:

<table>
  <thead>
    <tr>
      <th></th>
      <th>列車進入月台車站之站名</th>
      <th>行駛目的地</th>
      <th>資料更新日期</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>南港展覽館</td>
      <td>頂埔</td>
      <td>2018-10-15 22:14:25</td>
    </tr>
  </tbody>
</table>

然後在終端機輸入以下指令:

ng serve

再用瀏覽器開啟 localhost:4200 之後,便會看到下圖:

Imgur

如此一來,我們算是完成初步的 Template 架構。接下來,讓我們把剛剛美化過後的資料放進來吧!怎麼做呢?首先,我們可以先新增一個名為 station-list.const.ts 的檔案,然後在裡面加上以下程式碼:

export const stationList = [

];

接著再把美化過後的的資料放進去(只要放 [] 裡面的就好囉!):

Imgur

哇咧?!怎麼都整片紅紅的?!是不是什麼地方做錯了?!別慌,把滑鼠指標停靠在有著紅色波浪底線的地方看看:

Imgur

原來是 tslint 在提醒你,雙引號 " 應該要被換成單引號 '。既然如此,我們就把它替換掉就好啦!請按下 Ctrl + H 鍵(macOS 請按 command + option + F)開啟取代功能:

Imgur

並在「尋找」的欄位裡輸入 " 、「取代」的欄位裡輸入 ' 後,按下全部取代鍵:

Imgur

世界又再度恢復了和平~~,感謝飛天小女警的努力~~:

Imgur

接著到 app.component.ts 裡頭,我們把 stationList 給 import 進來使用,並將 title 改成 list,準備用來使用 list 裡的資料去讓畫面長出來:

import { Component } from '@angular/core';

// Constant
import { stationList } from './station-list.const';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  /**
   * 所有列車到站站名之資料
   *
   * @memberof AppComponent
   */
  list = stationList;

}

但我們要怎麼讓資料去幫我們把畫面長出來呢?先看一下 Template 的結構:

<table>
  <thead>
    <tr>
      <th></th>
      <th>列車進入月台車站之站名</th>
      <th>行駛目的地</th>
      <th>資料更新日期</th>
    </tr>
  </thead>
  <tbody>
    <tr>
      <td>1</td>
      <td>南港展覽館</td>
      <td>頂埔</td>
      <td>2018-10-15 22:14:25</td>
    </tr>
  </tbody>
</table>

其實如果可以在 Template 寫程式的話,或許大家都知道該怎麼做:

<table>
  <!-- thead 省略 -->
  <tbody>
  
    <!-- 如果可以在 Template 裡寫程式的話 -->
    <!-- 就在這裡寫個 For 迴圈 -->
    <!-- 有多少筆資料,就有多少 <tr></tr> -->
    <tr>
      <td>1</td>
      <td>南港展覽館</td>
      <td>頂埔</td>
      <td>2018-10-15 22:14:25</td>
    </tr>
        
  </tbody>
</table>

沒錯!其實很多語言都可以直接在 HTML 裡寫程式,Angular 也可以!在這邊,我們會用到的 Template 語法是-*ngFor,所以程式碼就會變得像是這樣:

<table>
  <!-- thead 省略 -->
  <tbody>
    <tr *ngFor="let item of list">
      <td>1</td>
      <td>南港展覽館</td>
      <td>頂埔</td>
      <td>2018-10-15 22:14:25</td>
    </tr>
  </tbody>
</table>

儲存完檔案後,趕快到瀏覽器上看結果:

Imgur

哇!Angular 真的幫我們用資料把畫面長出來了耶?!不過怎麼都是一樣的資料?!這時候就要趕快搭配我們不久前學到的插值表達式{{ }}

<table>
  <!-- thead 省略 -->
  <tbody>
    <tr *ngFor="let item of list">
      <td>1</td>
      <td>{{ item.Station }}</td>
      <td>{{ item.Destination }}</td>
      <td>{{ item.UpdateTime }}</td>
    </tr>
  </tbody>
</table>

儲存完檔案之後一樣趕快到瀏覽器看看:

Imgur

哇!全部都按照資料產生出畫面了耶?!是不是覺得非常簡單、輕鬆呢?!這時候眼睛比較利的朋友可能會發現:咦?編號全部都是 1 啊?!沒錯,因為我們還沒有把索引加進來:

<table>
  <!-- thead 省略 -->
  <tbody>
    <tr *ngFor="let item of list; index as i">
      <td>{{ i + 1 }}</td>
      <td>{{ item.Station }}</td>
      <td>{{ item.Destination }}</td>
      <td>{{ item.UpdateTime }}</td>
    </tr>
  </tbody>
</table>

感謝邦友 SuperMike 的分享, *ngFor="let item of list; index as i" 後面的 index as i 也可以用 let i = index 的方式宣告。如:*ngFor="let item of list; let i = index"

一樣改完要記得儲存,Angular CLI 才會幫你刷新頁面噢!加完索引的插值表達式之後,讓我們來看看畫面:

Imgur

這下子編號也完成了,只剩下最後一個資料更新日期的欄位還需要再調整一下。怎麼調整呢?!Angular 有提供一個原生的管道*(pipe)*- date 給我們使用。使用方式像是這樣:

<td>{{ item.UpdateTime | date: 'yyyy-MM-dd HH:mm:ss' }}</td>

如此一來這個功能就算完成啦!!

Imgur

剩下樣式的部份就看個人美感囉,來整理一下今天的程式碼吧!

app.component.html 的部份:

<table>
  <thead>
    <tr>
      <th></th>
      <th>列車進入月台車站之站名</th>
      <th>行駛目的地</th>
      <th>資料更新日期</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let item of list; index as i">
      <td>{{ i + 1 }}</td>
      <td>{{ item.Station }}</td>
      <td>{{ item.Destination }}</td>
      <td>{{ item.UpdateTime | date: 'yyyy-MM-dd HH:mm:ss' }}</td>
    </tr>
  </tbody>
</table>

app.component.ts 的部份:

import { Component } from '@angular/core';

// Constant
import { stationList } from './station-list.const';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  /**
   * 所有列車到站站名之資料
   *
   * @memberof AppComponent
   */
  list = stationList;

}

station-list.const.ts 的部份:

export const stationList = [
  {
    'Station': '三重國小站',
    'Destination': '南勢角站',
    'UpdateTime': '2018-10-15T22:14:41.557'
  },
  /*
   * 太長了,中間省略。
   */
  {
    'Station': '麟光站',
    'Destination': '南港展覽館站',
    'UpdateTime': '2018-10-15T22:14:41'
  }
];

怎麼樣?!Angular 滿好玩的吧?!很輕鬆、簡單地就可以實作一個小應用,如果今天換成 jQuery 來做這個功能的話,大概會變成像是這個樣子:

Imgur

是也不難啦,畢竟只是個小試牛刀而已。不過隨著程式的複雜程度提高,Angular 的優點會更明顯一些。下次我們再來做個比較複雜一點的應用吧!!

錯誤更新記錄

  • 2019/05/28 11:40 - 非常感謝邦友 SuperMike 的提醒,修正 *ngForindex 宣告沒有加上 let 關鍵字之問題。
  • 2019/06/13 15:30 - 非常感謝邦友 ogilice 的提醒,修正 *ngForindex 宣告多加了 let 關鍵字之問題。

上一篇
[Angular 深入淺出三十天] Day 04 - 資料夾結構說明
下一篇
[Angular 深入淺出三十天] Day 06 - 基礎結構說明(一)
系列文
Angular 深入淺出三十天33
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中
1
SuperMike
iT邦新手 5 級 ‧ 2019-05-24 15:54:10

世界又再度恢復了和平~~,感謝飛天小女警的努力~~:

看到這裡,噗ㄘ一笑

幫大大補充一下,<tr *ngFor="let item of list; index as i">可改寫成<tr *ngFor="let item of list; let i = index">

一天又平安的過去了,再次感謝飛天小女警的努力!

Leo iT邦新手 3 級 ‧ 2019-05-28 12:04:52 檢舉

Hi SuperMike,

身為一個宅宅工程師,飛天小女警是小時候的必修課程眼睛要夠利。

非常感謝您的糾正!我沒打到 let ,已修正文章內容!

ogilice iT邦新手 5 級 ‧ 2019-06-12 16:44:13 檢舉

版主後面是不是多打了一個let?

Leo iT邦新手 3 級 ‧ 2019-06-13 15:26:29 檢舉

Hi ogilice,

對!!我沒看清楚就加上去了,我的錯!!

感謝你!!

0
ming0212
iT邦新手 5 級 ‧ 2020-02-23 13:09:02

受益良多,最近接觸到angular這塊剛好需要看一下,還有練習跟詳細解說,寫得很好,大感謝!

Leo iT邦新手 3 級 ‧ 2020-02-24 09:01:28 檢舉

非常高興可以幫到你

0
fredfu5431
iT邦新手 5 級 ‧ 2020-03-02 14:36:18

您好:
我的station-list.const.ts如下(摘錄)

export const stationList = [
  {
    Station: '土城站',
    Destination: '頂埔站',
    UpdateTime: '2020 - 02 - 27T17: 07: 06.643'
  },
  {
    Station: '士林站',
    Destination: '象山站',
    UpdateTime: '2020 - 02 - 27T17: 07: 05.233'
  },

其他程式都跟前輩一樣,可是只顯示一行資料,時間也無法顯示,想請前輩指導,謝謝.
列車進入月台車站之站名 行駛目的地 資料更新日期
1 土城站 頂埔站

看更多先前的回應...收起先前的回應...
Leo iT邦新手 3 級 ‧ 2020-03-02 14:39:02 檢舉

Hi, fredfu5431

一定有地方不一樣才會造成結果不同唷!

你可以再仔細找找看,或是你再把你的程式碼貼上來讓我幫你找找看。 :)

您好:
app.component.ts如下:

import { Component } from '@angular/core';
import { stationList } from './station-list.const';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  list = stationList;
}

app.component.html如下:

<table>
  <thead>
    <tr>
      <th></th>
      <th>列車進入月台車站之站名</th>
      <th>行駛目的地</th>
      <th>資料更新日期</th>
    </tr>
  </thead>
  <tbody>
    <tr *ngFor="let item of list;index as i">
      <td>{{ i+1 }}</td>
      <td>{{ item.Station }}</td>
      <td>{{ item.Destination }}</td>
      <td>{{ item.UpdateTime | date: 'yyyy-MM-dd HH:mm:ss' }}</td>
    </tr>
  </tbody>
</table>

麻煩前輩了,謝謝.

Leo iT邦新手 3 級 ‧ 2020-03-02 17:23:45 檢舉

Hi fredfu5431,

我剛剛試了一下,是你 stationList 裡的資料欄位 UpdateTime 的格式不對噢!

你的資料長這樣:

UpdateTime: '2020 - 02 - 27T17: 07: 06.643'

我的資料長這樣:

UpdateTime: '2018-10-15T22:14:41.557'

無謂的空格會造成 DatePiper 解析資料的錯誤噢!

您好:
真的如前輩所言是格式錯誤,謝謝前輩願意花時間幫忙,感恩感恩!

0
kateliuyi
iT邦新手 5 級 ‧ 2021-02-20 14:47:59

好文章/images/emoticon/emoticon01.gif

Leo iT邦新手 3 級 ‧ 2021-02-20 15:31:38 檢舉

感謝支持^^

0
Yori
iT邦新手 5 級 ‧ 2022-03-02 17:38:41

請問要讓stationList裡的資料顯示,一定要使用ngFor="let item of list"嗎?
要辦法在component裡加工,直接跳過
ngFor的過程嗎?
因為要使用emailjs傳資料,但只能使用{{}},如果經過ngFor的話會傳不了

Leo iT邦新手 3 級 ‧ 2022-03-02 17:50:57 檢舉

ngFor 是給陣列用的範本語法,建議還是要加工一下喔!

我要留言

立即登入留言