Now.js Framework Documentation
CascadingSelectManager
CascadingSelectManager
ภาพรวม
CascadingSelectManager คือระบบจัดการ cascading/dependent select boxes ใน Now.js Framework โหลด options แบบ dynamic ตาม selection ก่อนหน้า
ใช้เมื่อ:
- Province → District → Subdistrict selects
- Category → Subcategory → Product selects
- Country → State → City selects
- Any dependent dropdown chains
ทำไมต้องใช้:
- ✅ AJAX loading พร้อม debounce
- ✅ Auto-disable empty selects
- ✅ Supports form integration
- ✅ Default option customization
- ✅ Auto-initialization from HTML
การใช้งานพื้นฐาน
HTML Declarative
<form id="address-form">
<!-- Parent select -->
<select name="province"
data-cascade-url="/api/provinces"
data-cascade-children="district"
data-cascade-placeholder="เลือกจังหวัด">
<option value="">โปรดเลือก...</option>
</select>
<!-- Child select (depends on province) -->
<select name="district"
data-cascade-url="/api/districts"
data-cascade-parent="province"
data-cascade-children="subdistrict"
data-cascade-placeholder="เลือกอำเภอ"
disabled>
<option value="">โปรดเลือก...</option>
</select>
<!-- Grandchild select (depends on district) -->
<select name="subdistrict"
data-cascade-url="/api/subdistricts"
data-cascade-parent="district"
data-cascade-placeholder="เลือกตำบล"
disabled>
<option value="">โปรดเลือก...</option>
</select>
</form>JavaScript API
// Initialize in container
CascadingSelectManager.initInContainer(document.getElementById('address-form'));
// Or create manually
CascadingSelectManager.create([
document.querySelector('[name="province"]'),
document.querySelector('[name="district"]'),
document.querySelector('[name="subdistrict"]')
], {
autoLoad: true,
autoDisable: true
});Data Attributes
| Attribute | Description |
|---|---|
data-cascade-url |
API URL สำหรับโหลด options |
data-cascade-parent |
name ของ parent select |
data-cascade-children |
name ของ child select(s) (comma-separated) |
data-cascade-placeholder |
Placeholder text |
data-cascade-params |
Additional query params (JSON) |
data-cascade-value-field |
Field name for value (default: 'id') |
data-cascade-label-field |
Field name for label (default: 'name') |
API Response Format
// Array of objects
[
{ id: 1, name: 'Bangkok' },
{ id: 2, name: 'Chiang Mai' },
{ id: 3, name: 'Phuket' }
]
// Or custom fields
[
{ code: 'BKK', title: 'Bangkok' },
{ code: 'CNX', title: 'Chiang Mai' }
]
// Use: data-cascade-value-field="code" data-cascade-label-field="title"Query parameters ที่ส่งไป:
- Parent field name = parent value
- Additional params from
data-cascade-params
GET /api/districts?province=1
GET /api/subdistricts?district=101การตั้งค่า
CascadingSelectManager.init({
// Loading indicator class
loadingClass: 'loading',
// Debounce delay (ms)
ajaxDelay: 300,
// Add default "Please select" option
defaultOption: true,
defaultOptionText: 'Please select...',
// Auto-load first select on init
autoLoad: true,
// Auto-disable empty selects
autoDisable: true,
// Custom placeholders per select
placeholders: {
province: 'เลือกจังหวัด',
district: 'เลือกอำเภอ'
},
debug: false
});API อ้างอิง
CascadingSelectManager.initInContainer(container)
Initialize cascading selects ใน container
| Parameter | Type | Description |
|---|---|---|
container |
HTMLElement | Form หรือ container element |
CascadingSelectManager.create(selects, options)
สร้าง cascading select chain
| Parameter | Type | Description |
|---|---|---|
selects |
Array | Array of select elements |
options |
object | Configuration options |
Returns: Object - Instance
CascadingSelectManager.reset(instance)
Reset ทุก select กลับค่าเริ่มต้น
| Parameter | Type | Description |
|---|---|---|
instance |
Object | Instance จาก create() |
CascadingSelectManager.destroy(instance)
ทำลาย instance
| Parameter | Type | Description |
|---|---|---|
instance |
Object | Instance |
CascadingSelectManager.getInstance(id)
รับ instance ตาม ID
CascadingSelectManager.getInstanceForElement(element)
รับ instance จาก select element
เหตุการณ์
| Event | เมื่อเกิด | Detail |
|---|---|---|
cascade:loading |
เริ่มโหลด options | {select, parent} |
cascade:loaded |
โหลดเสร็จ | {select, options, count} |
cascade:error |
โหลด error | {select, error} |
cascade:change |
Select เปลี่ยนค่า | {select, value, children} |
cascade:reset |
Reset ทั้งหมด | {instance} |
EventManager.on('cascade:loaded', (data) => {
console.log(`Loaded ${data.count} options for ${data.select.name}`);
});ตัวอย่างการใช้งานจริง
Thai Address Form
<div class="address-form" id="address-section">
<div class="form-group">
<label>จังหวัด</label>
<select name="province_id"
data-cascade-url="/api/address/provinces"
data-cascade-children="amphur_id"
data-cascade-value-field="id"
data-cascade-label-field="name_th">
<option value="">เลือกจังหวัด</option>
</select>
</div>
<div class="form-group">
<label>อำเภอ/เขต</label>
<select name="amphur_id"
data-cascade-url="/api/address/amphurs"
data-cascade-parent="province_id"
data-cascade-children="district_id"
disabled>
<option value="">เลือกอำเภอ</option>
</select>
</div>
<div class="form-group">
<label>ตำบล/แขวง</label>
<select name="district_id"
data-cascade-url="/api/address/districts"
data-cascade-parent="amphur_id"
data-cascade-children="zipcode"
disabled>
<option value="">เลือกตำบล</option>
</select>
</div>
<div class="form-group">
<label>รหัสไปรษณีย์</label>
<select name="zipcode"
data-cascade-url="/api/address/zipcodes"
data-cascade-parent="district_id"
disabled>
<option value="">เลือกรหัสไปรษณีย์</option>
</select>
</div>
</div>
<script>
document.addEventListener('DOMContentLoaded', () => {
CascadingSelectManager.initInContainer(document.getElementById('address-section'));
});
</script>Category Filter
// Product category → Subcategory → Brand
const instance = CascadingSelectManager.create([
categorySelect,
subcategorySelect,
brandSelect
], {
autoLoad: true,
defaultOptionText: 'ทั้งหมด'
});
// Listen for final selection
brandSelect.addEventListener('change', (e) => {
filterProducts({
category: categorySelect.value,
subcategory: subcategorySelect.value,
brand: e.target.value
});
});Pre-populated Values
<!-- สำหรับ edit form ที่มีค่าอยู่แล้ว -->
<select name="province" data-cascade-url="/api/provinces">
<option value="">เลือก</option>
<option value="1" selected>กรุงเทพฯ</option>
</select>
<select name="district"
data-cascade-url="/api/districts"
data-cascade-parent="province"
data-cascade-initial-value="101">
<option value="">เลือก</option>
</select>ข้อควรระวัง
⚠️ 1. Parent Name ต้องตรงกัน
<!-- ❌ parent ไม่ตรง -->
<select name="province_id">...</select>
<select data-cascade-parent="province">...</select>
<!-- ✅ ต้องตรงกัน -->
<select name="province">...</select>
<select data-cascade-parent="province">...</select>⚠️ 2. API Response Format
// ❌ Response format ไม่ถูก
{ success: true, data: [...] }
// ✅ Return array โดยตรง
[{ id: 1, name: 'Bangkok' }, ...]
// หรือ configure fields
data-cascade-value-field="id"
data-cascade-label-field="name"⚠️ 3. Initialize หลัง DOM Ready
// ❌ ก่อน DOM ready
CascadingSelectManager.initInContainer(document.getElementById('form'));
// ✅ หลัง DOM ready
document.addEventListener('DOMContentLoaded', () => {
CascadingSelectManager.initInContainer(document.getElementById('form'));
});เอกสารที่เกี่ยวข้อง
- SelectElementFactory - Select inputs
- FormManager - Form handling