Now.js Framework Documentation
FileElementFactory - คอมโพเนนต์อัปโหลดไฟล์
FileElementFactory - คอมโพเนนต์อัปโหลดไฟล์
คู่มือสำหรับ FileElementFactory คอมโพเนนต์อัปโหลดไฟล์ที่มีความสามารถครบครัน รองรับการแสดงตัวอย่าง ลากวาง เรียงลำดับ และตรวจสอบความถูกต้อง
📋 สารบัญ
- ภาพรวม
- การติดตั้งและเตรียมการ
- การใช้งานพื้นฐาน
- Attributes ใน HTML
- ตัวเลือกการตั้งค่า
- ฟีเจอร์
- การตรวจสอบไฟล์
- ระบบแสดงตัวอย่าง
- ลากและวาง
- เรียงลำดับไฟล์
- ไฟล์ที่มีอยู่แล้ว
- Events
- JavaScript API
- ตัวอย่างการใช้งาน
- Best Practices
ภาพรวม
FileElementFactory เป็น ElementFactory ที่เพิ่มความสามารถให้กับ file input element ด้วยฟีเจอร์ขั้นสูง เช่น การแสดงตัวอย่าง ลากและวาง การตรวจสอบไฟล์ การเรียงลำดับ และการทำงานร่วมกับ Form component ของ Now.js
ฟีเจอร์หลัก
- ✅ แสดงตัวอย่างแบบเรียลไทม์: แสดงภาพตัวอย่างของไฟล์ที่อัปโหลด
- ✅ ลากและวาง: อินเทอร์เฟซลากและวางที่ใช้งานง่าย
- ✅ ตรวจสอบไฟล์: ตรวจสอบประเภทและขนาดไฟล์
- ✅ เรียงลำดับไฟล์: จัดเรียงไฟล์ด้วยการลาก (ต้องใช้ Sortable.js)
- ✅ หลายไฟล์: รองรับการอัปโหลดไฟล์เดียวและหลายไฟล์
- ✅ ไฟล์ที่มีอยู่: โหลดและแสดงไฟล์ที่มีอยู่จากเซิร์ฟเวอร์
- ✅ ลบไฟล์: ลบไฟล์ก่อนส่งฟอร์ม
- ✅ ติดตามความคืบหน้า: แสดงความคืบหน้าการอัปโหลด
- ✅ ทำงานร่วมกับฟอร์ม: ทำงานร่วมกับ FormManager ได้อย่างลงตัว
- ✅ เริ่มต้นอัตโนมัติ: เพิ่มความสามารถให้ file input อัตโนมัติ
เมื่อไหร่ควรใช้ FileElementFactory
✅ ใช้ FileElementFactory เมื่อ:
- ต้องการอัปโหลดไฟล์พร้อมแสดงตัวอย่าง
- ต้องการฟีเจอร์ลากและวาง
- ต้องการตรวจสอบประเภทและขนาดไฟล์
- ต้องการแสดงไฟล์ที่อัปโหลดไว้แล้ว
- ต้องการเรียงลำดับไฟล์
- ต้องการทำงานร่วมกับฟอร์มอย่างลงตัว
❌ ไม่ควรใช้ FileElementFactory เมื่อ:
- ต้องการ file input แบบธรรมดา (ใช้
<input type="file">ปกติ) - ต้องการ logic การอัปโหลดแบบกำหนดเอง
- ไม่ต้องการฟีเจอร์เพิ่มเติมใดๆ
การติดตั้งและเตรียมการ
FileElementFactory เป็นส่วนหนึ่งของ Now.js Framework และลงทะเบียนกับ ElementManager อัตโนมัติ
Dependencies
- ElementFactory - คลาสพื้นฐาน
- EventSystemManager - จัดการ event
- FormError - แสดงข้อผิดพลาด
- Sortable.js (ตัวเลือก) - สำหรับเรียงลำดับไฟล์
- MediaViewer (ตัวเลือก) - สำหรับแสดงภาพแบบ modal
การลงทะเบียนอัตโนมัติ
// FileElementFactory ลงทะเบียนอัตโนมัติ
ElementManager.registerElement('file', FileElementFactory);
// <input type="file"> ทุกตัวจะได้รับการเพิ่มความสามารถอัตโนมัติการใช้งานพื้นฐาน
1. อัปโหลดไฟล์แบบธรรมดา
<input type="file"
id="avatar"
name="avatar"
accept="image/*">2. อัปโหลดไฟล์พร้อมแสดงตัวอย่าง
<input type="file"
id="avatar"
name="avatar"
data-preview="true"
accept="image/*">3. หลายไฟล์พร้อมลากและวาง
<input type="file"
id="files"
name="files"
multiple
data-preview="true"
data-drag-drop="true"
accept="image/*,application/pdf">4. ตัวอย่างครบครันพร้อมฟีเจอร์ทั้งหมด
<form data-form="upload">
<label for="files">อัปโหลดไฟล์</label>
<span class="form-control icon-upload">
<input type="file"
id="files"
name="files"
multiple
data-preview="true"
data-drag-drop="true"
data-sortable="true"
data-allow-remove-existing="true"
data-file-reference="url"
data-max-file-size="5242880"
accept="image/*,application/pdf"
placeholder="ลากไฟล์มาวางที่นี่ หรือคลิกเพื่อเลือก">
</span>
</form>Attributes ใน HTML
FileElementFactory รองรับ data attributes เหล่านี้สำหรับการตั้งค่า:
Attributes พื้นฐาน
| Attribute | ประเภท | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
data-preview |
boolean | false |
เปิดใช้งานการแสดงตัวอย่างไฟล์ |
data-drag-drop |
boolean | false |
เปิดใช้งานลากและวาง |
data-sortable |
boolean | false |
อนุญาตให้เรียงลำดับไฟล์ |
data-allow-remove-existing |
boolean | false |
อนุญาตให้ลบไฟล์ที่มีอยู่ |
multiple |
boolean | false |
อนุญาตให้เลือกหลายไฟล์ |
accept |
string | * |
ประเภทไฟล์ที่อนุญาต (เช่น "image/*,application/pdf") |
placeholder |
string | - | ข้อความ placeholder สำหรับ drop zone |
Attributes สำหรับอ้างอิงไฟล์
| Attribute | ประเภท | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
data-file-reference |
string | 'id' |
ชื่อฟิลด์สำหรับอ้างอิงไฟล์ (เช่น "url", "id") |
data-attr |
string | - | ผูกกับแหล่งข้อมูล (เช่น "value:files") |
data-files |
JSON | - | ข้อมูลไฟล์ที่มีอยู่ |
Attributes สำหรับตรวจสอบ
| Attribute | ประเภท | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
data-max-file-size |
number | 10485760 |
ขนาดไฟล์สูงสุดเป็น bytes (ค่าเริ่มต้น: 10MB) |
required |
boolean | false |
กำหนดให้ต้องอัปโหลดไฟล์ |
Attributes สำหรับเชื่อมต่อเซิร์ฟเวอร์
| Attribute | ประเภท | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
data-action-url |
string | - | API endpoint สำหรับจัดการไฟล์ (ลบ, เรียงลำดับ) |
Attribute สำหรับ Preview Container
| Attribute | ประเภท | ค่าเริ่มต้น | คำอธิบาย |
|---|---|---|---|
data-preview-container |
string | - | CSS selector สำหรับ preview container แบบกำหนดเอง |
ตัวเลือกการตั้งค่า
เมื่อสร้าง instance ด้วย JavaScript:
const instance = FileElementFactory.create(element, {
// แสดงตัวอย่าง
preview: true,
previewContainer: '.custom-preview',
// ลากและวาง
dragDrop: true,
// เรียงลำดับ
sortable: true,
// จัดการไฟล์
allowRemoveExisting: true,
fileReference: 'url',
// ตรวจสอบ
maxFileSize: 5 * 1024 * 1024, // 5MB
allowedMimeTypes: ['image/*', 'application/pdf'],
// เชื่อมต่อเซิร์ฟเวอร์
actionUrl: '/api/files',
// ไฟล์ที่มีอยู่
existingFiles: [
{ url: 'files/photo.jpg', name: 'photo.jpg' },
{ url: 'files/document.pdf', name: 'document.pdf' }
],
// UI
placeholder: 'ลากไฟล์มาวางที่นี่ หรือคลิกเพื่อเลือก',
downloadEnabled: true,
// Callbacks
onChange: (files, element) => {
console.log('ไฟล์เปลี่ยนแปลง:', files);
},
onError: (error) => {
console.error('ข้อผิดพลาด:', error);
}
});ฟีเจอร์
1. แสดงตัวอย่างแบบเรียลไทม์
แสดงภาพย่อของไฟล์ที่อัปโหลด:
<input type="file"
name="images"
multiple
data-preview="true"
accept="image/*">ความสามารถ:
- ภาพย่อสำหรับไฟล์รูปภาพ
- ไอคอนไฟล์สำหรับเอกสาร (PDF, Word, Excel ฯลฯ)
- แสดงชื่อและขนาดไฟล์
- ปุ่มลบสำหรับแต่ละไฟล์
2. ลากและวาง
เปิดใช้งานการอัปโหลดไฟล์แบบลากและวาง:
<input type="file"
name="files"
multiple
data-drag-drop="true"
placeholder="ลากไฟล์มาวางที่นี่ หรือคลิกเพื่อเลือก">ความสามารถ:
- พื้นที่วางไฟล์ที่มองเห็นชัดเจน
- แสดงผลตอบรับเมื่อลากผ่าน
- รองรับการวางหลายไฟล์
- สำรองด้วยการคลิกเลือก
3. หลายไฟล์
อัปโหลดหลายไฟล์พร้อมกัน:
<input type="file"
name="files"
multiple
data-preview="true">4. ตรวจสอบไฟล์
ตรวจสอบประเภทและขนาดไฟล์:
<input type="file"
name="avatar"
accept="image/jpeg,image/png,image/webp"
data-max-file-size="2097152">
<!-- ขนาดสูงสุด: 2MB -->กฎการตรวจสอบ:
- ตรวจสอบประเภทไฟล์ (MIME types และนามสกุล)
- ตรวจสอบขนาดไฟล์
- แสดงข้อผิดพลาดอัตโนมัติ
- ทำงานร่วมกับฟอร์ม
5. เรียงลำดับไฟล์
จัดเรียงไฟล์ที่อัปโหลดด้วยการลาก (ต้องใช้ Sortable.js):
<input type="file"
name="gallery"
multiple
data-preview="true"
data-sortable="true"
data-action-url="/api/files/sort">ความสามารถ:
- จุดจับสำหรับลากแต่ละไฟล์
- แสดงผลตอบรับระหว่างลาก
- บันทึกลำดับไปยังเซิร์ฟเวอร์อัตโนมัติ
- ย้อนกลับเมื่อเกิดข้อผิดพลาด
6. ไฟล์ที่มีอยู่แล้ว
โหลดและแสดงไฟล์ที่มีอยู่จากเซิร์ฟเวอร์:
<input type="file"
name="files"
multiple
data-preview="true"
data-attr="value:files"
data-file-reference="url"
data-allow-remove-existing="true"
data-action-url="/api/files">รูปแบบ Response จากเซิร์ฟเวอร์:
{
"data": {
"files": [
{
"url": "uploads/photo.jpg",
"name": "photo.jpg",
"size": 1258291
},
{
"url": "uploads/document.pdf",
"name": "document.pdf",
"size": 524288
}
]
}
}การตรวจสอบไฟล์
ประเภทไฟล์ที่รองรับ
MIME types ที่อนุญาตตามค่าเริ่มต้น:
allowedMimeTypes: [
'image/*',
'application/pdf',
'application/msword',
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'application/vnd.ms-excel',
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'text/plain',
'application/zip',
'application/x-zip-compressed'
]การตรวจสอบแบบกำหนดเอง
<!-- รับเฉพาะรูปภาพ -->
<input type="file" accept="image/*">
<!-- รับเฉพาะรูปภาพบางประเภท -->
<input type="file" accept="image/jpeg,image/png,image/webp">
<!-- รับรูปภาพและ PDF -->
<input type="file" accept="image/*,application/pdf">
<!-- รับตามนามสกุล -->
<input type="file" accept=".jpg,.jpeg,.png,.pdf">ตรวจสอบขนาดไฟล์
<!-- สูงสุด 5MB -->
<input type="file" data-max-file-size="5242880">
<!-- สูงสุด 10MB (ค่าเริ่มต้น) -->
<input type="file" data-max-file-size="10485760">ข้อผิดพลาดการตรวจสอบ
ข้อผิดพลาดจะแสดงอัตโนมัติผ่าน FormError:
// ข้อความแสดงข้อผิดพลาดจะถูกแปลภาษา
"ขนาดไฟล์ต้องไม่เกิน {maxsize}"
"ประเภทไฟล์ไม่ได้รับอนุญาต"
"จำเป็นต้องเลือกไฟล์"ระบบแสดงตัวอย่าง
แสดงตัวอย่างอัตโนมัติ
ตัวอย่างจะถูกสร้างอัตโนมัติเมื่อ data-preview="true":
<span class="form-control icon-upload">
<input type="file"
name="files"
multiple
data-preview="true">
</span>HTML ที่สร้างขึ้น:
<span class="form-control icon-upload">
<input type="file" name="files" multiple>
<div class="file-preview">
<div class="preview-item" data-file-name="photo.jpg">
<span class="image-preview" style="background-image: url(...)"></span>
<div class="file-info">photo.jpg (1.2 MB)</div>
<button type="button" class="icon-delete" title="ลบไฟล์"></button>
</div>
</div>
</span>Preview Container แบบกำหนดเอง
<input type="file"
name="files"
data-preview="true"
data-preview-container="#custom-preview">
<div id="custom-preview"></div>ความสามารถของการแสดงตัวอย่าง
- ภาพย่อ: รูปภาพพื้นหลังสำหรับรูปถ่าย
- ไอคอนไฟล์: ไอคอนสำหรับเอกสาร (PDF, Word, Excel, ZIP)
- ข้อมูลไฟล์: แสดงชื่อและขนาด
- ปุ่มลบ: ลบไฟล์ก่อนอัปโหลด
- คลิกเพื่อดู: คลิกรูปภาพเพื่อเปิดใน modal (ต้องใช้ MediaViewer)
ลากและวาง
ลากและวางพื้นฐาน
<input type="file"
name="files"
multiple
data-drag-drop="true"
placeholder="ลากไฟล์มาวางที่นี่ หรือคลิกเพื่อเลือก">Drop Zone ที่สร้างขึ้น
<div class="file-drop-zone">
<input type="file" name="files" multiple>
<div class="file-drop-content">
<div class="file-drop-message">ลากไฟล์มาวางที่นี่ หรือคลิกเพื่อเลือก</div>
</div>
<div class="file-preview">
<!-- รายการตัวอย่าง -->
</div>
</div>CSS Classes
| Class | เมื่อใช้ | คำอธิบาย |
|---|---|---|
file-drop-zone |
ตลอดเวลา | Container ของ drop zone |
drag-over |
ระหว่างลาก | กำลังลากไฟล์ผ่าน |
file-drop-content |
ตลอดเวลา | พื้นที่เนื้อหาของ drop zone |
file-drop-message |
ตลอดเวลา | ข้อความของ drop zone |
ตัวอย่างการจัดรูปแบบ
.file-drop-zone {
border: 2px dashed #ccc;
border-radius: 8px;
padding: 20px;
text-align: center;
transition: all 0.3s;
}
.file-drop-zone.drag-over {
border-color: #007bff;
background-color: #f0f8ff;
}
.file-drop-message {
color: #666;
font-size: 16px;
padding: 40px 20px;
}JavaScript API
รับ Instance
// จาก element
const instance = ElementManager.getInstance(element);
// จาก ID
const element = document.getElementById('files');
const instance = ElementManager.getInstance(element);Instance Methods
// ล้างไฟล์ทั้งหมด
instance.clearFiles();
// ตรวจสอบไฟล์
const isValid = instance.validateFiles();
// อัปโหลดไฟล์
const result = await instance.upload({
url: '/api/upload',
data: { userId: 123 }
});Static Methods
// ตรวจสอบไฟล์เดียว
await FileElementFactory.validateFile(file, config);
// จัดรูปแบบขนาดไฟล์
const size = FileElementFactory.formatFileSize(1258291);
// คืนค่า: "1.2 MB"
// รับ class ไอคอนไฟล์
const icon = FileElementFactory.getFileIcon('document.pdf');
// คืนค่า: "icon-pdf"
// ตรวจสอบประเภทไฟล์
const isValid = FileElementFactory.isValidFileType(file, ['image/*', 'application/pdf']);ตัวอย่างการใช้งาน
ตัวอย่าง 1: อัปโหลดรูปโปรไฟล์
<form data-form="profile" method="POST" action="/api/profile">
<label for="avatar">รูปโปรไฟล์</label>
<span class="form-control icon-image">
<input type="file"
id="avatar"
name="avatar"
data-preview="true"
accept="image/*"
data-max-file-size="2097152"
placeholder="เลือกรูปโปรไฟล์ของคุณ">
</span>
<button type="submit">บันทึกโปรไฟล์</button>
</form>ตัวอย่าง 2: หลายไฟล์พร้อมลากและวาง
<form data-form="documents" method="POST" action="/api/documents">
<label for="files">อัปโหลดเอกสาร</label>
<span class="form-control icon-upload">
<input type="file"
id="files"
name="files"
multiple
data-preview="true"
data-drag-drop="true"
accept="image/*,application/pdf"
data-max-file-size="10485760"
placeholder="ลากไฟล์มาวางที่นี่ หรือคลิกเพื่อเลือก">
</span>
<button type="submit">อัปโหลดไฟล์</button>
</form>ตัวอย่าง 3: แกลเลอรีที่เรียงลำดับได้
<form data-form="gallery" data-load-api="/api/gallery">
<label for="photos">แกลเลอรีรูปภาพ</label>
<span class="form-control icon-image">
<input type="file"
id="photos"
name="photos"
multiple
data-preview="true"
data-drag-drop="true"
data-sortable="true"
data-allow-remove-existing="true"
data-file-reference="id"
data-action-url="/api/gallery"
data-attr="value:photos"
accept="image/*"
placeholder="ลากรูปภาพมาวางที่นี่">
</span>
<button type="submit">บันทึกแกลเลอรี</button>
</form>Best Practices
1. ตรวจสอบประเภทไฟล์เสมอ
<!-- ✅ ดี: ระบุประเภทไฟล์ชัดเจน -->
<input type="file" accept="image/jpeg,image/png,image/webp">
<!-- ❌ ไม่ดี: ไม่มีการตรวจสอบ -->
<input type="file">2. กำหนดขนาดไฟล์ที่เหมาะสม
<!-- ✅ ดี: จำกัด 5MB สำหรับรูปภาพ -->
<input type="file"
accept="image/*"
data-max-file-size="5242880">
<!-- ❌ ไม่ดี: ค่าเริ่มต้น 10MB อาจใหญ่เกินไป -->
<input type="file" accept="image/*">3. ใช้ Preview เพื่อ UX ที่ดีขึ้น
<!-- ✅ ดี: แสดงตัวอย่าง -->
<input type="file"
data-preview="true"
accept="image/*">
<!-- ❌ ไม่ดี: ไม่มีผลตอบรับทางภาพ -->
<input type="file" accept="image/*">4. เปิดใช้งานลากและวางสำหรับหลายไฟล์
<!-- ✅ ดี: ลากและวางสำหรับหลายไฟล์ -->
<input type="file"
multiple
data-drag-drop="true"
data-preview="true">
<!-- ❌ ไม่ดี: หลายไฟล์แต่ไม่มีลากและวาง -->
<input type="file" multiple>5. ใส่ Placeholder ที่ชัดเจน
<!-- ✅ ดี: คำแนะนำที่ชัดเจน -->
<input type="file"
data-drag-drop="true"
placeholder="ลากรูปภาพมาวางที่นี่ หรือคลิกเพื่อเลือก (สูงสุด 5MB)">
<!-- ❌ ไม่ดี: Placeholder ทั่วไป -->
<input type="file" data-drag-drop="true">6. จัดการไฟล์ที่มีอยู่อย่างถูกต้อง
<!-- ✅ ดี: โหลดและอนุญาตให้ลบ -->
<input type="file"
data-attr="value:files"
data-file-reference="url"
data-allow-remove-existing="true"
data-action-url="/api/files">
<!-- ❌ ไม่ดี: ไม่มีวิธีจัดการไฟล์ที่มีอยู่ -->
<input type="file" data-attr="value:files">7. ใช้การทำงานร่วมกับฟอร์ม
<!-- ✅ ดี: ทำงานร่วมกับฟอร์ม -->
<form data-form="upload" data-ajax-submit="true">
<input type="file" name="files" required>
<button type="submit">อัปโหลด</button>
</form>
<!-- ❌ ไม่ดี: จัดการด้วยตนเอง -->
<input type="file" id="files">
<button onclick="uploadFiles()">อัปโหลด</button>เอกสารที่เกี่ยวข้อง
- FormManager - การจัดการและตรวจสอบฟอร์ม
- ElementFactory - คลาสพื้นฐานสำหรับ element factories
- EventSystemManager - ระบบจัดการ event
- ตัวอย่างการอัปโหลดไฟล์ - ตัวอย่างที่ใช้งานได้จริง