iT邦幫忙

2025 iThome 鐵人賽

DAY 24
2
Modern Web

原生元件養成計畫:Web Component系列 第 24

Day 24: Web Component 應用-整合框架 Angular

  • 分享至 

  • xImage
  •  

在前一篇文章,我們已經發布完成第一個 Web Component。
還記得在 Day 2 時有提到過:

使用 Web Component 開發的元件可以在 React、Vue、Angular 或 Vanilla JS 中使用,所以可以讓不同框架之間能夠更好地彼此合作,利用小小的共享元件,來增加開發的效率。

所以接下來的幾篇文章,會針對 Web Component 與三大框架的應用來做討論!
這一篇我們先來聊聊 Web Component 與 Angular。

Web Component 與 Anglar

第一個框架選擇 Angular,主要是因為對於 Angular 比較熟悉,而且 Angular 可以說是三大框架中對於 Web Component 最友善的框架了,並沒有太多複雜的設定值,基本上只要安裝完自訂元件就可以開始使用了。(絕對不是因為我都用 Angular 開發才這樣說的)。

在 Angular 使用自訂元件建立會員註冊表單

接下來在我們要在 Angular 內把 un-custom-input 當作註冊帳號的表單的欄位使用。
其中需要包含姓名帳號email密碼,還有一顆送出按鈕,再整合原生的 <form> 元件來開發。

其實 Angular 裡面還有另一個方法,也就是 formGroup,但這部分在這系列先不做討論。有興趣的大家,可以使用關鍵字 NG_VALUE_ACCESSOR 來找到相關資訊。

基本配置

  1. 首先,你需要先有一個 Angular 的專案
    開始實作前,你需要先安裝 Angular CLI,並且利用 ng new 建立一個 angular 專案。

  2. 安裝自訂元件 un-custom-input

npm install un-custom-input
  1. main.ts (Angular bootstrap 的入口) 中引入 un-custom-input確保自訂元件在 Angular component render 前就已註冊好
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';
import 'un-custom-input';

bootstrapApplication(AppComponent, appConfig)
  .catch((err) => console.error(err));

重點:CUSTOM_ELEMENTS_SCHEMA

要能夠在 Angular 專案中使用自訂元件,需要加入一個的 Schema:CUSTOM_ELEMENTS_SCHEMA
在沒有加入前,Angular 模板檢查時會把他不認識的未知元素當成錯誤,所以需要把 CUSTOM_ELEMENTS_SCHEMA 加到 module 的 schemas。
這樣 Angular 就可以允許模板使用包含有 - 的自訂元素(是否記得之前提過 Web Component 的命名規則是至少要有一個 -,所以是符合這個規則的)。

在 Angular 不同的版本會有不同的加入方式:

  • standalone component 架構:在 @Component 中引入。
import { Component, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

@Component({
  selector: 'app-root',
  standalone: true,
  imports: [
    // 略...    
  ],
  templateUrl: './app.component.html',
  styleUrl: './app.component.css',
  schemas: [
    CUSTOM_ELEMENTS_SCHEMA
  ]
})
  • AppModule 的架構:在 @NgModule 中引入。
import { NgModule, CUSTOM_ELEMENTS_SCHEMA } from '@angular/core';

@NgModule({
  declarations: [ /* ... */ ],
  imports: [ /* ... */ ],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule {}

將自訂元件加入 Angular Template

先試著加入一個元件在 template:

<un-custom-input></un-custom-input>

使用 ng s 來查看元件是否有出現:
demo

做到這一步,其實你已經成功的在 Angular 中使用自訂元件了。

那麼接下來就是實作打造完整的註冊表單囉!

  • 完善表單的 Template 架構:
    app.component.html
<form class="form">
  <div class="input-container">
    <label>姓名</label>
    <un-custom-input
      placeholder="請輸入暱稱"
      required
      pattern=".{2,}"
      pattern-message="暱稱至少 2 個字元"
    >
    </un-custom-input>
  </div>

  <div class="input-container">
    <label>帳號</label>
    <un-custom-input
      placeholder="請輸入帳號"
      required
      pattern="^[a-zA-Z0-9_]{4,}$"
      pattern-message="帳號至少 4 碼,僅能含英文、數字與底線"
    >
    </un-custom-input>
  </div>

  <div class="input-container">
    <label>Email</label>
    <un-custom-input
      placeholder="請輸入 Email"
      required
      pattern="^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$"
      pattern-message="請輸入有效的 Email"
    >
    </un-custom-input>
  </div>

  <div class="input-container">
    <label>密碼</label>
    <un-custom-input
      #password1
      type="password"
      placeholder="請輸入密碼"
      required
      pattern="(?=.*[A-Z])(?=.*[0-9]).{8,}"
      pattern-message="密碼至少 8 碼,需包含大寫字母與數字"
    >
    </un-custom-input>
  </div>

  <div class="input-container">
    <label>確認密碼</label>
    <un-custom-input
      #password2
      type="password"
      placeholder="請再次輸入密碼"
      required
    >
    </un-custom-input>
  </div>

  <button class="submit-btn">註冊</button>
</form>
  • 完善表單及自訂元件的樣式:
    再設計自訂元件時,我們有開放了 CSS Variable 以及 ::part 提供外部做樣式的修改,接下來就一起樣式加入吧!
    app.component.css
/* 改變 un-custom-input 的 CSS Variable */
un-custom-input {
  --ci-border-color: #cccccc;
}

/* 利用 ::part(custom-input) 來改變 input 輸入框的樣式 */
un-custom-input::part(custom-input) {
  padding: 6px 12px;
  border-radius: 8px;
  font-size: 16px;
}

/* 賦予表單基本的樣式 */
.form {
  display: flex;
  flex-direction: column;
  gap: 12px;
  padding: 16px;
}

.input-container {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.input-container label {
  font-weight: 500;
  color: #333333;
}

.submit-btn {
  margin-top: 16px;
  padding: 10px 16px;
  background-color: #8c67c9;
  color: white;
  border: none;
  border-radius: 8px;
  font-size: 16px;
  cursor: pointer;
}
  • 加入元件的方法與邏輯
  1. 取得 form 的 ElementRef:
// 在 class 內加入 ViewChild 取得 <form> 元素
@ViewChild('form') formRef!: ElementRef;
  1. 加入表單註冊按鈕按下時的邏輯
  onSubmit(event: Event) {
    event.preventDefault();
    const inputs = this.formRef.nativeElement.querySelectorAll('un-custom-input');
    let allValid = true;

    inputs.forEach((input: CustomInputElement) => {
      input.touchAndValidate();

      if (!input.checkValidity()) {
        allValid = false;
      }
    });

    if (!allValid) {
      return;
    }
  }

上一篇
Day 23: Web Component 的使用說明 Readme
系列文
原生元件養成計畫:Web Component24
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言