npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

thai-address-select

v1.0.5

Published

Linked province → district → subdistrict dropdowns for Thailand (Vanilla JS).

Downloads

11

Readme

thai-address-select

English | ไทย


English

A lightweight TypeScript library for creating linked dropdowns for Thai address selection (Province → District → Subdistrict) with automatic postal code retrieval.

Features

  • 🇹🇭 Complete Thai address database - All provinces, districts, subdistricts, and postal codes
  • 🔗 Auto-linked dropdowns - Selecting province automatically filters districts, and so on
  • 📮 Automatic postal code - Postal code is retrieved when address is complete
  • 🎨 Framework agnostic - Works with Vanilla JS, React, Vue, Angular, etc.
  • 💪 TypeScript support - Full type definitions included
  • 📦 Zero dependencies - Lightweight and fast
  • 🚀 Easy to use - Simple API with minimal setup

Installation

npm install thai-address-select

Quick Start

Basic HTML + JavaScript

<!DOCTYPE html>
<html>
<body>
  <select id="province"></select>
  <select id="district"></select>
  <select id="subDistrict"></select>
  <input id="zipCode" readonly>

  <script type="module">
    import { ThaiAddressSelect } from './node_modules/thai-address-select/dist/src/index.js';
    import { loadData } from './node_modules/thai-address-select/dist/src/utils/filterAddress.js';

    // 1. Load data first
    await loadData();

    // 2. Initialize
    const thaiAddress = new ThaiAddressSelect({
      provinceEl: document.getElementById("province"),
      districtEl: document.getElementById("district"),
      subDistrictEl: document.getElementById("subDistrict")
    });

    // 3. Listen for changes
    thaiAddress.addEventListener("selectChange", (e) => {
      document.getElementById("zipCode").value = e.detail.zip_code || "";
      console.log(e.detail); // { province, district, subDistrict, zip_code }
    });
  </script>
</body>
</html>

Note: Make sure to run this through a local server (e.g., npx serve .) because ES modules don't work with file:// protocol.

Usage with React

"use client";

import { useEffect, useRef, useState } from 'react';

export default function AddressForm() {
  const provinceRef = useRef<HTMLSelectElement>(null);
  const districtRef = useRef<HTMLSelectElement>(null);
  const subDistrictRef = useRef<HTMLSelectElement>(null);
  const [zipCode, setZipCode] = useState('');

  useEffect(() => {
    let thaiAddress: any;

    const init = async () => {
      // Dynamic import to avoid SSR issues
      const { ThaiAddressSelect } = await import('thai-address-select');
      const { loadData } = await import('thai-address-select');

      await loadData();

      if (provinceRef.current && districtRef.current && subDistrictRef.current) {
        thaiAddress = new ThaiAddressSelect({
          provinceEl: provinceRef.current,
          districtEl: districtRef.current,
          subDistrictEl: subDistrictRef.current
        });

        thaiAddress.addEventListener('selectChange', (e: any) => {
          setZipCode(e.detail.zip_code || '');
        });
      }
    };

    init();

    return () => thaiAddress?.destroy();
  }, []);

  return (
    <div>
      <select ref={provinceRef} className="w-full p-2 border rounded" />
      <select ref={districtRef} className="w-full p-2 border rounded" />
      <select ref={subDistrictRef} className="w-full p-2 border rounded" />
      <input value={zipCode} readOnly className="w-full p-2 border rounded bg-gray-100" />
    </div>
  );
}

API Reference

ThaiAddressSelect

Constructor Options
interface ThaiAddressSelectOptions {
  provinceEl: HTMLSelectElement;      // Required: Province dropdown element
  districtEl: HTMLSelectElement;      // Required: District dropdown element
  subDistrictEl: HTMLSelectElement;   // Required: Subdistrict dropdown element
  placeholder?: {                     // Optional: Custom placeholder text
    province?: string;
    district?: string;
    subDistrict?: string;
  };
  initialValue?: {                    // Optional: Set initial values
    province?: string;
    district?: string;
    subDistrict?: string;
  };
}
Methods

getValue()
Returns current selected values including postal code.

const value = thaiAddress.getValue();
// Returns: { province?: string, district?: string, subDistrict?: string, zip_code?: string }

setValue(value)
Set values programmatically.

thaiAddress.setValue({
  province: "กรุงเทพมหานคร",
  district: "เขตบางรัก",
  subDistrict: "มหาพฤฒาราม"
});

destroy()
Remove event listeners and clean up.

thaiAddress.destroy();
Events

selectChange
Fired when all dropdowns (province, district, subdistrict) have values.

thaiAddress.addEventListener("selectChange", (e) => {
  console.log(e.detail.province);     // "กรุงเทพมหานคร"
  console.log(e.detail.district);     // "เขตบางรัก"
  console.log(e.detail.subDistrict);  // "มหาพฤฒาราม"
  console.log(e.detail.zip_code);     // "10500"
});

provinceChange, districtChange, subDistrictChange
Fired when individual dropdown changes.

thaiAddress.addEventListener("provinceChange", (e) => {
  console.log(e.detail.province);
});

Utility Functions

These functions can be used independently without creating a ThaiAddressSelect instance.

loadData()
Must be called before using any other functions.

import { loadData } from 'thai-address-select';
await loadData();

getProvinces()
Returns array of all province names (sorted in Thai alphabetical order).

import { getProvinces } from 'thai-address-select';
const provinces = getProvinces();
// ["กระบี่", "กรุงเทพมหานคร", ...]

getDistricts(province)
Returns array of district names for a given province.

import { getDistricts } from 'thai-address-select';
const districts = getDistricts("กรุงเทพมหานคร");
// ["เขตบางกอกน้อย", "เขตบางกอกใหญ่", ...]

getSubDistricts(province, district)
Returns array of subdistrict names for a given province and district.

import { getSubDistricts } from 'thai-address-select';
const subDistricts = getSubDistricts("กรุงเทพมหานคร", "เขตบางรัก");
// ["มหาพฤฒาราม", "สีลม", "สุริยวงศ์", ...]

getzip_code(province, district, subDistrict)
Returns postal code for a given address.

import { getzip_code } from 'thai-address-select';
const zipCode = getzip_code("กรุงเทพมหานคร", "เขตบางรัก", "มหาพฤฒาราม");
// "10500"

Customization

Custom Placeholders

const thaiAddress = new ThaiAddressSelect({
  provinceEl: provinceEl,
  districtEl: districtEl,
  subDistrictEl: subDistrictEl,
  placeholder: {
    province: "Select Province",
    district: "Select District",
    subDistrict: "Select Subdistrict"
  }
});

Initial Values

const thaiAddress = new ThaiAddressSelect({
  provinceEl: provinceEl,
  districtEl: districtEl,
  subDistrictEl: subDistrictEl,
  initialValue: {
    province: "กรุงเทพมหานคร",
    district: "เขตบางรัก",
    subDistrict: "มหาพฤฒาราม"
  }
});

Data Source

The library includes a complete database of Thai administrative divisions:

  • 77 Provinces
  • 928 Districts
  • 7,255 Subdistricts
  • Postal codes for all areas

Browser Support

  • Modern browsers with ES6+ support
  • Chrome, Firefox, Safari, Edge (latest versions)

Author

rratchapol


ไทย

ไลบรารี TypeScript น้ำหนักเบาสำหรับสร้าง dropdown เลือกที่อยู่ไทยแบบเชื่อมโยง (จังหวัด → อำเภอ → ตำบล) พร้อมดึงรหัสไปรษณีย์อัตโนมัติ

ฟีเจอร์

  • 🇹🇭 ฐานข้อมูลที่อยู่ไทยครบถ้วน - จังหวัด อำเภอ ตำบล และรหัสไปรษณีย์ทั้งหมด
  • 🔗 Dropdown เชื่อมโยงอัตโนมัติ - เลือกจังหวัดแล้วกรองอำเภอให้อัตโนมัติ
  • 📮 รหัสไปรษณีย์อัตโนมัติ - ดึงรหัสไปรษณีย์เมื่อเลือกที่อยู่ครบถ้วน
  • 🎨 ใช้ได้กับทุก Framework - รองรับ Vanilla JS, React, Vue, Angular ฯลฯ
  • 💪 รองรับ TypeScript - มี type definitions ครบถ้วน
  • 📦 ไม่มี dependencies - เบาและรวดเร็ว
  • 🚀 ใช้งานง่าย - API เรียบง่าย ติดตั้งไม่ยุ่งยาก

การติดตั้ง

npm install thai-address-select

เริ่มต้นใช้งาน

HTML + JavaScript พื้นฐาน

<!DOCTYPE html>
<html>
<body>
  <select id="province"></select>
  <select id="district"></select>
  <select id="subDistrict"></select>
  <input id="zipCode" readonly>

  <script type="module">
    import { ThaiAddressSelect } from './node_modules/thai-address-select/dist/src/index.js';
    import { loadData } from './node_modules/thai-address-select/dist/src/utils/filterAddress.js';

    // 1. โหลดข้อมูลก่อน
    await loadData();

    // 2. สร้าง instance
    const thaiAddress = new ThaiAddressSelect({
      provinceEl: document.getElementById("province"),
      districtEl: document.getElementById("district"),
      subDistrictEl: document.getElementById("subDistrict")
    });

    // 3. รอรับการเปลี่ยนแปลง
    thaiAddress.addEventListener("selectChange", (e) => {
      document.getElementById("zipCode").value = e.detail.zip_code || "";
      console.log(e.detail); // { province, district, subDistrict, zip_code }
    });
  </script>
</body>
</html>

หมายเหตุ: ต้องรันผ่าน local server (เช่น npx serve .) เพราะ ES modules ใช้งานไม่ได้กับ file:// protocol

การใช้งานกับ React

"use client";

import { useEffect, useRef, useState } from 'react';

export default function AddressForm() {
  const provinceRef = useRef<HTMLSelectElement>(null);
  const districtRef = useRef<HTMLSelectElement>(null);
  const subDistrictRef = useRef<HTMLSelectElement>(null);
  const [zipCode, setZipCode] = useState('');

  useEffect(() => {
    let thaiAddress: any;

    const init = async () => {
      // Dynamic import เพื่อหลีกเลี่ยงปัญหา SSR
      const { ThaiAddressSelect } = await import('thai-address-select');
      const { loadData } = await import('thai-address-select');

      await loadData();

      if (provinceRef.current && districtRef.current && subDistrictRef.current) {
        thaiAddress = new ThaiAddressSelect({
          provinceEl: provinceRef.current,
          districtEl: districtRef.current,
          subDistrictEl: subDistrictRef.current
        });

        thaiAddress.addEventListener('selectChange', (e: any) => {
          setZipCode(e.detail.zip_code || '');
        });
      }
    };

    init();

    return () => thaiAddress?.destroy();
  }, []);

  return (
    <div>
      <select ref={provinceRef} className="w-full p-2 border rounded" />
      <select ref={districtRef} className="w-full p-2 border rounded" />
      <select ref={subDistrictRef} className="w-full p-2 border rounded" />
      <input value={zipCode} readOnly className="w-full p-2 border rounded bg-gray-100" />
    </div>
  );
}

API Reference

ThaiAddressSelect

ตัวเลือก Constructor
interface ThaiAddressSelectOptions {
  provinceEl: HTMLSelectElement;      // จำเป็น: Element dropdown จังหวัด
  districtEl: HTMLSelectElement;      // จำเป็น: Element dropdown อำเภอ
  subDistrictEl: HTMLSelectElement;   // จำเป็น: Element dropdown ตำบล
  placeholder?: {                     // ไม่จำเป็น: ข้อความ placeholder
    province?: string;
    district?: string;
    subDistrict?: string;
  };
  initialValue?: {                    // ไม่จำเป็น: ค่าเริ่มต้น
    province?: string;
    district?: string;
    subDistrict?: string;
  };
}
Methods

getValue()
คืนค่าที่เลือกปัจจุบัน รวมรหัสไปรษณีย์

const value = thaiAddress.getValue();
// คืนค่า: { province?: string, district?: string, subDistrict?: string, zip_code?: string }

setValue(value)
ตั้งค่าผ่านโค้ด

thaiAddress.setValue({
  province: "กรุงเทพมหานคร",
  district: "เขตบางรัก",
  subDistrict: "มหาพฤฒาราม"
});

destroy()
ลบ event listeners และทำความสะอาด

thaiAddress.destroy();
Events

selectChange
ทำงานเมื่อ dropdown ทั้งหมด (จังหวัด อำเภอ ตำบล) มีค่า

thaiAddress.addEventListener("selectChange", (e) => {
  console.log(e.detail.province);     // "กรุงเทพมหานคร"
  console.log(e.detail.district);     // "เขตบางรัก"
  console.log(e.detail.subDistrict);  // "มหาพฤฒาราม"
  console.log(e.detail.zip_code);     // "10500"
});

provinceChange, districtChange, subDistrictChange
ทำงานเมื่อ dropdown แต่ละตัวเปลี่ยนแปลง

thaiAddress.addEventListener("provinceChange", (e) => {
  console.log(e.detail.province);
});

ฟังก์ชันเสริม

ฟังก์ชันเหล่านี้สามารถใช้งานแยกโดยไม่ต้องสร้าง instance ของ ThaiAddressSelect

loadData()
ต้องเรียกก่อนใช้ฟังก์ชันอื่นๆ

import { loadData } from 'thai-address-select';
await loadData();

getProvinces()
คืน array ชื่อจังหวัดทั้งหมด (เรียงตามตัวอักษรไทย)

import { getProvinces } from 'thai-address-select';
const provinces = getProvinces();
// ["กระบี่", "กรุงเทพมหานคร", ...]

getDistricts(province)
คืน array ชื่ออำเภอของจังหวัดที่ระบุ

import { getDistricts } from 'thai-address-select';
const districts = getDistricts("กรุงเทพมหานคร");
// ["เขตบางกอกน้อย", "เขตบางกอกใหญ่", ...]

getSubDistricts(province, district)
คืน array ชื่อตำบลของจังหวัดและอำเภอที่ระบุ

import { getSubDistricts } from 'thai-address-select';
const subDistricts = getSubDistricts("กรุงเทพมหานคร", "เขตบางรัก");
// ["มหาพฤฒาราม", "สีลม", "สุริยวงศ์", ...]

getzip_code(province, district, subDistrict)
คืนรหัสไปรษณีย์ของที่อยู่ที่ระบุ

import { getzip_code } from 'thai-address-select';
const zipCode = getzip_code("กรุงเทพมหานคร", "เขตบางรัก", "มหาพฤฒาราม");
// "10500"

การปรับแต่ง

ปรับแต่ง Placeholder

const thaiAddress = new ThaiAddressSelect({
  provinceEl: provinceEl,
  districtEl: districtEl,
  subDistrictEl: subDistrictEl,
  placeholder: {
    province: "เลือกจังหวัด",
    district: "เลือกอำเภอ",
    subDistrict: "เลือกตำบล"
  }
});

ตั้งค่าเริ่มต้น

const thaiAddress = new ThaiAddressSelect({
  provinceEl: provinceEl,
  districtEl: districtEl,
  subDistrictEl: subDistrictEl,
  initialValue: {
    province: "กรุงเทพมหานคร",
    district: "เขตบางรัก",
    subDistrict: "มหาพฤฒาราม"
  }
});

ข้อมูลที่รวมอยู่

ไลบรารีรวมฐานข้อมูลการแบ่งเขตการปกครองของไทยครบถ้วน:

  • 77 จังหวัด
  • 928 อำเภอ/เขต
  • 7,255 ตำบล/แขวง
  • รหัสไปรษณีย์ครบทุกพื้นที่

Browser ที่รองรับ

  • Browser สมัยใหม่ที่รองรับ ES6+
  • Chrome, Firefox, Safari, Edge (เวอร์ชันล่าสุด)

ผู้พัฒนา

rratchapol