Now.js Framework Documentation

Now.js Framework Documentation

FileElementFactory - คอมโพเนนต์อัปโหลดไฟล์

TH 01 Dec 2025 13:48

FileElementFactory - คอมโพเนนต์อัปโหลดไฟล์

คู่มือสำหรับ FileElementFactory คอมโพเนนต์อัปโหลดไฟล์ที่มีความสามารถครบครัน รองรับการแสดงตัวอย่าง ลากวาง เรียงลำดับ และตรวจสอบความถูกต้อง

📋 สารบัญ

  1. ภาพรวม
  2. การติดตั้งและเตรียมการ
  3. การใช้งานพื้นฐาน
  4. Attributes ใน HTML
  5. ตัวเลือกการตั้งค่า
  6. ฟีเจอร์
  7. การตรวจสอบไฟล์
  8. ระบบแสดงตัวอย่าง
  9. ลากและวาง
  10. เรียงลำดับไฟล์
  11. ไฟล์ที่มีอยู่แล้ว
  12. Events
  13. JavaScript API
  14. ตัวอย่างการใช้งาน
  15. 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>

เอกสารที่เกี่ยวข้อง