iT邦幫忙

2021 iThome 鐵人賽

DAY 4
0
Modern Web

關於我作夢變成工程師這檔事(Angular 篇)系列 第 4

第 4 天 英雄有偶包怎麼辦|*ngFor、JsonPipe、Angular Material、Mat-Card、Mat-Button

前情提要

昨天我們已經成功地使用 HttpClient 發送 Http 請求,從 mock db 取得了英雄資料,並將資料列印在 console 裏。今天我們要進一步在畫面上顯示資料,並且加上 Angular Material 的元件,優化 app 畫面表現。

006

(現在,我們要召喚英靈們...)

我們不是已經召喚出來了嗎,他們在 console 裡躺得好好的呢。

(他們可是英靈,人家是有偶像包袱的,嫌你醜,不想被召喚。)

話要說清楚啊,妳應該是說這個 app 都沒樣式畫面醜吧?

(總之就是你自己得好好打理打理。)

妳是說好好處理 app 畫面吧!我發現妳說話越來越省略我很困擾。

(快去打理吧。)

使用 *ngFor 顯示英雄資料

首先,我們先使用 Angular 提供的結構指令 *ngFor 來顯示陣列資料。在 hero-list.component.html 中輸入:

<pre *ngFor="let hero of heroList">
    {{ hero | json }}
</pre>

這是一個很快可以將物件資料呈現在畫面上的寫法,簡單說明這些語法提供的效果:

  • *ngFor: 這是 Angular 的結構性指令,能夠依照陣列資料的數量,將掛載此指令以下(含)的 HTML 標籤依照陣列資料的數量重複顯示出來。
  • JsonPipe: 把一個值轉換成 JSON 字串格式。在除錯時很有用。
  • pre:HTML 提供的 <pre> 標籤,會將標籤中的資料依原格式顯示,這會讓物件資料的排版更好地閱讀

上面的程式碼輸出的結果如下,我在開發時很常使用它們來確認取得的資料:
https://ithelp.ithome.com.tw/upload/images/20210919/201283956k1b4jgvfN.png

將資料放到畫面上後,接著我們就要使用 Angular Material 元件來改善畫面體驗。

安裝 Angular Material

不得不說,現在要在專案中添加 Angular Material 簡直太容易了,只要進入專案目錄執行:

ng add @angular/material

它會詢問幾個設定配置問題,我一樣都是選擇預設值(Enter 鍵連發)。

接著馬上來試試看 Angular Material 提供給我們的元件,稍微逛了一下文件,作為展示英雄資訊,覺得可以讓每位英雄的資訊都用一個卡片來呈現。那我們就來試試看吧!

將文件中的範例 Copy Paste 到 hero-list.component.html 中,並使用 *ngFor 放上英雄資料:

  <mat-card class="hero-item" *ngFor="let hero of heroList">
    <mat-card-header>
      <div mat-card-avatar class="example-header-image"></div>
      <mat-card-title>{{ hero.name }}</mat-card-title>
      <mat-card-subtitle>Dog Breed</mat-card-subtitle>
    </mat-card-header>
    <img mat-card-image src="https://material.angular.io/assets/img/examples/shiba2.jpg" alt="Photo of a Shiba Inu">
    <mat-card-content>
      <p>
        The Shiba Inu is the smallest of the six original and distinct spitz breeds of dog from Japan.
        A small, agile dog that copes very well with mountainous terrain, the Shiba Inu was originally
        bred for hunting.
      </p>
    </mat-card-content>
    <mat-card-actions>
      <button mat-button>LIKE</button>
      <button mat-button>SHARE</button>
    </mat-card-actions>
  </mat-card>

首先,Angular Material 是將不同的元件封裝成不同的 module,所以我們在使用之前,需要先在 module 檔匯入對應的 Angular Material Module,所以我們打開 app.module.ts,在 imports 陣列中加入 MatCardModule

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule } from '@angular/common/http';

import { MatCardModule } from '@angular/material/card';

import { AppComponent } from './app.component';
import { HeroListComponent } from './hero-list/hero-list.component';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

@NgModule({
  declarations: [
    AppComponent,
    HeroListComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    BrowserAnimationsModule,
    MatCardModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

可以看到,目前我們並沒有那麼多資料需要顯示(subtitle、description),因此我們只是在 title 的資料顯示欄位,使用 Angular 的文字插值(interpolation),也就是兩個大括弧 {{ hero.name }} 來將資料顯示在畫面上。目前畫面會這樣呈現:

https://ithelp.ithome.com.tw/upload/images/20210919/20128395p1VdtZM9FX.png

我們很快就會發現幾個問題:

  • 呂布變狗了!...這不是問題,每位英雄都變狗了,那是因為現階段我們沒有提供給他們圖片,這裏顯示的 Angular Material 預設的狗狗。
  • 一個狗狗就佔滿整個版面。這是樣式問題,所以我們等等會寫一些 CSS 來優化它們。
  • 這個按鈕看起來很陽春,Angular Material 文件上的按鈕比較有質感,可是我們是直接 Copy 文件上的範例程式碼欸,怎麼會這樣?

針對最後一個問題,這是因為 Angular Material 的文件 Mat-Card 提供的範例程式碼就使用了 Mat-Button 提供的功能。目前,我們並沒有在 AppModule 匯入 MatButtonModule,所以我們的按鈕看起來比較沒質感。讓我們來匯入它:

(略)

import { MatCardModule } from '@angular/material/card';
import { MatButtonModule } from '@angular/material/button';

(略)

@NgModule({
  (略)
  imports: [
    BrowserModule,
    HttpClientModule,
    BrowserAnimationsModule,
    MatCardModule,
    MatButtonModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

之後我們在打開 hero-list.component.html 將它的外層加上一個 <div class="hero-container"> 標籤:

<div class="hero-container">
  <mat-card class="hero-item" *ngFor="let hero of heroList">
    (略)
  </mat-card>
</div>

接著,hero-list.component.css 添加一些樣式:

.hero-container {
  display: flex;
  flex-wrap: wrap;
  justify-content: center;
}

.hero-item {
  flex-basis: 300px;
}

這樣英雄列表就會如下呈現啦:

https://ithelp.ithome.com.tw/upload/images/20210919/20128395rkBJYypI34.png

就把人類存亡的命運交給他們吧>///////////<


上一篇
第 3 天 「速速前呂布奉先!」|NgModule、HttpClientModule、新增元件
下一篇
第 5 天 還我漂漂拳| property binding、interface
系列文
關於我作夢變成工程師這檔事(Angular 篇)14

尚未有邦友留言

立即登入留言