跳到主要內容

PhoneInput

PhoneInput 元件提供了一個使用者友善的國際電話號碼輸入欄位。它與 react-hook-form 無縫整合,並包含一個帶有國旗和國碼的可搜尋國家選擇器、自動號碼格式化,以及由 google-libphonenumber 支援的強大驗證功能。

此元件旨在與其他表單元素(例如 CountrySelectAddressForm)協同工作,透過將其選定的國家與共享的表單欄位同步。

運作方式

該元件利用 react-international-phone 函式庫實現其核心功能,並將其包裝以提供與 react-hook-form 和 Material-UI 的深度整合。當使用者選擇一個國家或輸入號碼時,該元件會更新表單狀態中對應的欄位。當另一個元件修改表單中連結的國家欄位時,它也會自動更新其國家選擇。

PhoneInput

屬性

PhoneInput 元件接受所有標準的 Material-UI TextField 屬性,此外還包括以下特定屬性:

屬性類型是否必須預設值描述
namestring-用於向 react-hook-form 註冊電話號碼的欄位名稱。
countryFieldNamestring'billing_address.country'儲存所選國家 ISO2 代碼的表單欄位名稱。這使得電話輸入的國家可以與表單的其他部分(例如地址元件)同步。

使用方式

若要使用 PhoneInput 元件,您必須將其包裝在 react-hook-formFormProvider 中。以下範例展示了一個包含驗證的基本實作。

首先,您需要函式庫提供的非同步驗證函式。

phone-validator.js

javascript
// src/libs/phone-validator.js
import { getPhoneUtil } from '@blocklet/payment-react/libs/phone-validator';

export const validatePhoneNumber = async (phoneNumber) => {
  if (!phoneNumber) return true;
  try {
    const util = await getPhoneUtil();
    const parsed = util.parseAndKeepRawInput(phoneNumber);
    return util.isValidNumber(parsed);
  } catch (err) {
    console.error('Phone validation error:', err);
    // 如果函式庫載入失敗,則退回使用簡單的正規表示式
    const pattern = /^[+]?[(]?[0-9]{3}[)]?[-\s.]?[0-9]{3}[-\s.]?[0-9]{4,6}$/im;
    return pattern.test(phoneNumber) || 'Invalid phone number';
  }
};

現在,您可以在您的表單元件中使用此驗證器。

MyPaymentForm.tsx

jsx
import { FormProvider, useForm } from 'react-hook-form';
import { Button, Box } from '@mui/material';
import { PhoneInput } from '@blocklet/payment-react';
import { validatePhoneNumber } from '../libs/phone-validator'; // 根據需要調整路徑

export default function MyPaymentForm() {
  const methods = useForm({
    mode: 'onBlur',
    defaultValues: {
      phone: '',
      'billing_address.country': 'us', // 預設國家
    },
  });

  const onSubmit = (data) => {
    alert(JSON.stringify(data, null, 2));
  };

  return (
    <FormProvider {...methods}>
      <form onSubmit={methods.handleSubmit(onSubmit)}>
        <Box display="flex" flexDirection="column" gap={2}>
          <PhoneInput
            label="Phone Number"
            name="phone"
            // 連結到表單狀態中的國家欄位
            countryFieldName="billing_address.country"
            // 新增驗證規則
            rules={{
              validate: async (value) => {
                const isValid = await validatePhoneNumber(value);
                return isValid || 'Please enter a valid phone number.';
              },
            }}
            fullWidth
          />
          <Button type="submit" variant="contained">
            Submit
          </Button>
        </Box>
      </form>
    </FormProvider>
  );
}

解釋

  1. `FormProvider`

    整個表單,包括 PhoneInput,都被包裝在 FormProvider 中,以提供必要的表單情境。

  2. `rules`

    我們將一個非同步的 validate 函式傳遞給 rules 屬性。react-hook-form 在驗證期間將會等待此函式解析完成。validatePhoneNumber 公用程式被呼叫以執行檢查。

與 AddressForm 整合

PhoneInput 的真正強大之處在於與 AddressForm 一同使用時才能展現。由於兩個元件可以連結到同一個國家欄位(預設為 billing_address.country),因此在 AddressForm 中變更國家將會自動更新 PhoneInput 中的國旗和國碼。

關於此整合的完整範例,請參閱 AddressForm 的文件。