ฟอร์มที่อยู่แบบเต็ม
กรอกบ้านเลขที่ หมู่ ซอย ถนน พร้อมเลือกที่อยู่ตามลำดับชั้นในฟอร์มเดียว
ThaiAddressForm เหมาะกับฟอร์มที่ต้องการที่อยู่แบบเต็ม คือบ้านเลขที่/หมู่/ซอย/ถนน บวกกับตำบล อำเภอ/เขต และจังหวัด โดยฝัง cascade select ไว้ภายในให้แล้ว
'use client'
import { ThaiAddressForm } from '@/components/thai-address-form'
export default function AddressFormDemo() {
return <ThaiAddressForm onValueChange={(address) => console.log(address)} />
}ติดตั้ง
npx react-thaizip add address-formCLI เลือกไฟล์ให้ตาม style ที่ init บันทึกไว้: โปรเจกต์ที่มี components.json ของ shadcn/ui จะได้ไฟล์ที่ประกอบจาก primitives ของ shadcn (Base UI, Radix หรือ React Aria) นอกนั้นได้แบบ vanilla
วิธีใช้
import { ThaiAddressForm } from '@/components/thai-address-form'<ThaiAddressForm onValueChange={(address) => console.log(address)} />ค่าใน onValueChange คือ FullThaiAddress | null จะไม่เป็น null ก็ต่อเมื่อกรอกบ้านเลขที่แล้วและเลือกที่อยู่ตามลำดับชั้นครบทั้งสามระดับ
ตัวอย่าง
กรอกข้อมูลภาษาอังกฤษ
ใช้ locale="en" เพื่อแสดงป้ายกำกับและตัวเลือกเป็นภาษาอังกฤษ ทั้งฟิลด์ข้อความของตัวเองและ cascade select ที่ฝังอยู่
'use client'
import { ThaiAddressForm } from '@/components/thai-address-form'
export default function AddressFormEn() {
return <ThaiAddressForm locale="en" onValueChange={(address) => console.log(address)} />
}ควบคุมค่าจากภายนอก
ส่ง value เพื่อควบคุมค่าทั้งชุด หรือ defaultValue เพื่อตั้งค่าเริ่มต้น การเลือกที่อยู่ตามลำดับชั้นที่ยังเลือกไม่ครบจะไม่ถูกล้าง แม้ value ที่ควบคุมอยู่จะเป็น null
ค่าปัจจุบัน
null
'use client'
import { useState } from 'react'
import { ThaiAddressForm, type FullThaiAddress } from '@/components/thai-address-form'
export default function AddressFormControlled() {
const [address, setAddress] = useState<FullThaiAddress | null>(null)
return (
<div className="flex flex-col gap-3">
<ThaiAddressForm value={address} onValueChange={setAddress} />
<div>
<button type="button" className="rounded-md border border-input bg-background px-3 py-1.5 text-sm hover:bg-accent" onClick={() => setAddress(null)}>
ล้างค่า
</button>
</div>
<p className="text-sm font-medium">ค่าปัจจุบัน</p>
<pre className="max-h-72 overflow-auto rounded-md border bg-muted p-3 text-xs">{JSON.stringify(address, null, 2)}</pre>
</div>
)
}ปิดใช้งาน
ส่ง disabled เพื่อปิดทุกช่องกรอกและทุก select
'use client'
import { ThaiAddressForm } from '@/components/thai-address-form'
export default function AddressFormDisabled() {
return <ThaiAddressForm disabled />
}ไม่ผ่านการตรวจสอบ
ส่ง aria-invalid เพื่อทำเครื่องหมายว่าช่องกรอกทั้งสี่และ trigger ของ cascade ไม่ผ่านการตรวจสอบ
'use client'
import { ThaiAddressForm } from '@/components/thai-address-form'
export default function AddressFormInvalid() {
return <ThaiAddressForm aria-invalid />
}ปรับข้อความ
ใช้ texts สำหรับป้ายกำกับและ placeholder ของคอมโพเนนต์นี้ และ cascadeTexts สำหรับ cascade select ที่ฝังอยู่
import { ThaiAddressForm } from '@/components/thai-address-form'
export default function AddressFormTexts() {
return (
<ThaiAddressForm
texts={{
houseNoLabel: 'บ้านเลขที่ / ห้อง',
houseNoPlaceholder: 'เช่น 99/9 ห้อง 1203',
streetLabel: 'อาคาร / ถนน',
}}
/>
)
}ใช้ในฟอร์ม
ฟอร์มแบบหน้าชำระเงิน: มีช่องชื่อผู้รับและเบอร์โทรคู่กับที่อยู่ พร้อมปุ่มยกเลิกและบันทึก การส่ง name จะสร้าง hidden inputs แปดช่อง FormData ธรรมดาจึงได้ที่อยู่ครบทั้งชุด ดูรูปแบบอื่นได้ที่ การใช้งานร่วมกับฟอร์ม
'use client'
import { useState, type FormEvent } from 'react'
import { ThaiAddressForm } from '@/components/thai-address-form'
export default function AddressFormSubmit() {
const [payload, setPayload] = useState<Record<string, FormDataEntryValue> | null>(null)
function handleSubmit(event: FormEvent<HTMLFormElement>) {
event.preventDefault()
setPayload(Object.fromEntries(new FormData(event.currentTarget)))
}
return (
<form className="flex flex-col gap-4" onSubmit={handleSubmit} onReset={() => setPayload(null)}>
<div className="grid gap-4 sm:grid-cols-2">
<label className="flex flex-col gap-1.5 text-sm font-medium">
ชื่อผู้รับ
<input name="recipient" required className="h-9 rounded-md border border-input bg-background px-3 text-sm" />
</label>
<label className="flex flex-col gap-1.5 text-sm font-medium">
เบอร์โทรศัพท์
<input name="phone" type="tel" required className="h-9 rounded-md border border-input bg-background px-3 text-sm" />
</label>
</div>
<ThaiAddressForm name="address" required />
<div className="flex justify-end gap-2">
<button type="reset" className="rounded-md border border-input bg-background px-3 py-1.5 text-sm hover:bg-accent">
ยกเลิก
</button>
<button type="submit" className="rounded-md bg-primary px-3 py-1.5 text-sm font-medium text-primary-foreground hover:bg-primary/90">
บันทึกที่อยู่
</button>
</div>
<p className="text-sm font-medium">FormData ที่ส่ง</p>
<pre className="max-h-72 overflow-auto rounded-md border bg-muted p-3 text-xs">{JSON.stringify(payload, null, 2)}</pre>
</form>
)
}API Reference
| Prop | Type | ค่าเริ่มต้น | รายละเอียด |
|---|---|---|---|
value | FullThaiAddress | null | — | ค่าที่ควบคุมอยู่; ส่ง null เพื่อล้าง |
defaultValue | FullThaiAddress | null | — | ค่าเริ่มต้นของโหมด uncontrolled เติมทั้งช่องข้อความและ cascade ที่ฝังอยู่ |
onValueChange | (address: FullThaiAddress | null) => void | — | เรียกเมื่อบ้านเลขที่ไม่ว่างและเลือกครบทั้งสามระดับ หรือเมื่อค่ากลับมาไม่ครบอีกครั้ง |
name | string | — | สร้าง hidden inputs 8 ช่อง: 4 ช่องของ cascade (-subdistrict/-district/-province/-zipcode) และ 4 ช่องของคอมโพเนนต์นี้ (-houseno/-moo/-soi/-street) |
locale | 'th' | 'en' | 'th' | ภาษาของข้อความและป้ายกำกับ ทั้งของคอมโพเนนต์นี้และ cascade ที่ฝังอยู่ |
texts | Partial<ThaiAddressFormTexts> | — | แทนที่ป้ายกำกับและ placeholder ของบ้านเลขที่/หมู่/ซอย/ถนน |
cascadeTexts | Partial<ThaiAddressCascadeSelectTexts> | — | ส่งต่อเป็น texts ของ cascade select ที่ฝังอยู่ |
indexLoad | 'mount' | 'visible' | 'mount' | ส่งต่อไปยังตัวโหลดดัชนีที่อยู่ของ cascade ที่ฝังอยู่ |
disabled | boolean | false | ปิดใช้งานทุกช่องข้อความและ cascade ที่ฝังอยู่ |
required | boolean | false | กำหนดให้ช่องบ้านเลขที่และ cascade ต้องมีค่า (หมู่/ซอย/ถนนยังไม่บังคับ) |
aria-invalid | React.AriaAttributes['aria-invalid'] | — | ทำเครื่องหมายว่าช่องข้อความทั้งสี่และ trigger ของ cascade ไม่ผ่านการตรวจสอบ |
onBlur | React.FocusEventHandler<HTMLInputElement> | — | ทำงานเฉพาะเมื่อช่องบ้านเลขที่สูญเสียโฟกัส |
onError | (error: Error) => void | — | ทำงานเมื่อโหลดดัชนีที่อยู่ไม่สำเร็จ (จัดการโดย cascade ที่ฝังอยู่) |
className | string | — | wrapper หลัก |
labelClassName | string | — | ป้ายกำกับของช่องข้อความและ cascade |
inputClassName | string | — | ช่องบ้านเลขที่/หมู่/ซอย/ถนน |
triggerClassName | string | — | trigger ของ select และช่องรหัสไปรษณีย์ใน cascade |
popupClassName | string | — | กล่องตัวเลือกของ cascade |
itemClassName | string | — | แต่ละตัวเลือกของ cascade |
ref | React.Ref<HTMLInputElement> | — | ส่งต่อไปยังช่องบ้านเลขที่ |
ดูเพิ่มเติม
ดู การใช้งานร่วมกับฟอร์ม สำหรับการส่งค่าที่อยู่ และ การปรับแต่ง สำหรับปรับหน้าตา ส่วนคอมโพเนนต์ที่ฝังอยู่ ดู cascade select