react-thaizip

react-hook-form address field

Wrap the cascade select in react-hook-form's Controller to bind it to an existing form's validation and state

ThaiAddressFormField is for forms that already use react-hook-form and want the address bound directly into form state, instead of reading it from hidden inputs. Its prop shape is deliberately different from the other components: pass control/name/rules the same way you would to react-hook-form's own useController, and there is no value/onValueChange/hidden inputs.

Install

npx react-thaizip add address-form-field

The command adds the component, the embedded thai-address-cascade-select.tsx file, utils, the address-index loading hook, and the cascade-state hook to the directories recorded in thaizip.config.json. It installs react-hook-form if missing.

Basic usage

Import from the location generated in your project, along with useForm from react-hook-form:

import { useForm } from 'react-hook-form'
import type { ResolvedThaiAddress } from 'thaizip'
import { ThaiAddressFormField } from '@/components/thai-address-form-field'

type FormValues = {
  address: ResolvedThaiAddress | null
}

export function AddressField() {
  const { control, handleSubmit } = useForm<FormValues>({ defaultValues: { address: null } })

  return (
    <form onSubmit={handleSubmit((data) => console.log(data.address))}>
      <ThaiAddressFormField
        control={control}
        name="address"
        rules={{ validate: (value) => value !== null || 'Please select a complete address.' }}
      />
      <button type="submit">Submit</button>
    </form>
  )
}

The name you pass ("address" above) must have type ResolvedThaiAddress | null in the form's value type. react-hook-form's own handleSubmit reads the value directly — this component renders no hidden inputs.

Thai input

ฟิลด์ในฟอร์ม (react-hook-form)

cascade select ที่ครอบด้วย Controller ตรวจสอบและส่งค่าผ่าน react-hook-form

จังหวัด
อำเภอ/เขต
ตำบล/แขวง
รหัสไปรษณีย์

English input

Use locale="en" for English labels and options in the embedded cascade select.

Form field (react-hook-form)

A Controller-wrapped cascade select, validated and submitted through react-hook-form.

Province
District
Sub-district
Postal code

Validation with a rule

Pass rules the same way you would to react-hook-form's Controller/useController. This example requires a complete address before the form can submit; the error message renders as a <p role="alert"> below the cascade select.

Form field (react-hook-form)

A Controller-wrapped cascade select, validated and submitted through react-hook-form.

Province
District
Sub-district
Postal code
Submitted value
null

Disabled

Pass disabled to disable every select in the embedded cascade.

Form field (react-hook-form)

A Controller-wrapped cascade select, validated and submitted through react-hook-form.

Province
District
Sub-district
Postal code

Props

react-hook-form fields

PropTypeDescription
controlControl<TFieldValues>The control value from react-hook-form's useForm().
nameFieldPath<TFieldValues>The form field's path; its value type must be ResolvedThaiAddress | null.
rulesOmit<RegisterOptions<TFieldValues, FieldPath<TFieldValues>>, 'valueAsNumber' | 'valueAsDate' | 'setValueAs' | 'disabled'>Forwarded to react-hook-form's Controller for validation.

Options and text

PropTypeDescription
locale'th' | 'en'Label and option locale for the embedded cascade select; defaults to 'th'.
textsPartial<ThaiAddressCascadeSelectTexts>Forwarded as the embedded cascade select's own texts prop.
disabledbooleanDisables every select in the embedded cascade select.

Class slots

PropApplied to
classNameThe <div> wrapping the cascade select and its validation message
labelClassNameThe cascade select's labels
triggerClassNameThe cascade select's triggers and postal-code input
popupClassNameThe cascade select's option popups
itemClassNameEach of the cascade select's option items
errorClassNameThe role="alert" validation message shown when validation fails

This component accepts no value/onValueChange/ref/name (for a hidden input) like the other components do — react-hook-form reads and writes the value through the control/name you pass instead.

See Customization to change the presentation. If your form doesn't use react-hook-form, see cascade select or address form, which use the usual value/onValueChange/hidden-input shape.

On this page