JS Event, Form และ CRUD


JS CRUD

ตัวอย่าง Form และ CRUD Simulation (All Input Types)


7️⃣ Form, Modal และ CRUD (จำลองฐานข้อมูลด้วย Array)

ตัวอย่างนี้แสดงผลตารางด้วย **PHP** ส่วนการทำงาน CRUD (Insert/Update/Delete) ยังใช้ **JavaScript** (จำลองฐานข้อมูลด้วย Array)

ผลลัพธ์การทำงาน (หน้าแสดงข้อมูล)

ID ชื่อ (Text) อายุ (Num) วันเกิด (Date) ตำแหน่ง (Select) เพศ (Radio) สีโปรด (Color) สถานะ (Check)
1สมชาย ใจดี301995-05-15DeveloperMale #00ffffใช้งาน
2สมหญิง รักเรียน252000-11-20DesignerFemale #ff0000ไม่ใช้งาน

โค้ด PHP/JavaScript Logic


                        <?php
// PHP Script สำหรับการเริ่มต้นข้อมูล (Simulated DB)
// ในสถานการณ์จริง ข้อมูลนี้จะถูกดึงมาจากฐานข้อมูล MySQL
$simulatedDB_php = [
    [ 'id' => 1, 'name' => 'สมชาย ใจดี', 'email' => 'somchai@example.com', 'age' => 30, 'birthDate' => '1995-05-15', 'position' => 'Developer', 'gender' => 'Male', 'favColor' => '#00ffff', 'isActive' => true ],
    [ 'id' => 2, 'name' => 'สมหญิง รักเรียน', 'email' => 'somying@example.com', 'age' => 25, 'birthDate' => '2000-11-20', 'position' => 'Designer', 'gender' => 'Female', 'favColor' => '#ff0000', 'isActive' => false ]
];

// PHP Function เพื่อแปลงข้อมูลสถานะ (Boolean) เป็น HTML Badge
function getStatusBadge_php($isActive) {
    if ($isActive) {
        return '<span class="status-badge" style="background-color: lightgreen; color: #333;">ใช้งาน</span>';
    } else {
        return '<span class="status-badge" style="background-color: red; color: white;">ไม่ใช้งาน</span>';
    }
}

// PHP Function เพื่อแสดงข้อมูลในตาราง
// **ใช้ data-record-id สำหรับ JS Event Listener**
function renderTableBody_php($data) {
    if (empty($data)) {
        echo '<tr><td colspan="8" style="text-align: center;">ไม่มีข้อมูลในระบบ</td></tr>';
        return;
    }

    foreach ($data as $record) {
        $isActiveBadge = getStatusBadge_php($record['isActive']);
        $colorHtml = '<span class="color-display" style="background-color: ' . htmlspecialchars($record['favColor']) . ';"></span>';

        // Echoing HTML Row using PHP. Added class 'edit-row-trigger' for easy JS selection.
        echo '<tr class="edit-row-trigger" data-record-id="' . htmlspecialchars($record['id']) . '">';
        echo '<td>' . htmlspecialchars($record['id']) . '</td>';
        echo '<td>' . htmlspecialchars($record['name']) . '</td>';
        echo '<td>' . htmlspecialchars($record['age']) . '</td>';
        echo '<td>' . htmlspecialchars($record['birthDate']) . '</td>';
        echo '<td>' . htmlspecialchars($record['position']) . '</td>';
        echo '<td>' . htmlspecialchars($record['gender']) . '</td>';
        echo '<td>' . $colorHtml . ' ' . htmlspecialchars($record['favColor']) . '</td>';
        echo '<td>' . $isActiveBadge . '</td>';
        echo '</tr>';
    }
}
?>
            
            <div class="row">
                <div class="col-lg-12">
                    <h4 class="text-info">ผลลัพธ์การทำงาน (หน้าแสดงข้อมูล)</h4>
                    <div class="result-demo">
                        <button id="addNewBtn" class="action-button" style="background-color: lightgreen; color: #333;">+ เพิ่มข้อมูลใหม่ (Insert)</button>
                        <p id="messageArea" style="margin-top: 15px; font-weight: bold; color: orange;"></p>
                        
                        <table id="dataTable">
                            <thead>
                                <tr>
                                    <th>ID</th>
                                    <th>ชื่อ (Text)</th>
                                    <th>อายุ (Num)</th>
                                    <th>วันเกิด (Date)</th>
                                    <th>ตำแหน่ง (Select)</th>
                                    <th>เพศ (Radio)</th>
                                    <th>สีโปรด (Color)</th>
                                    <th>สถานะ (Check)</th>
                                </tr>
                            </thead>
                            <tbody id="dataBody">
                                <?php renderTableBody_php($simulatedDB_php); ?>
                            </tbody>
                        </table>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <div id="addModal" class="simple-modal-backdrop">
        <div class="simple-modal-content">
            <div class="simple-modal-header">
                <h3 style="color:#00ffff;">เพิ่มข้อมูลผู้ใช้ใหม่ (INSERT)</h3>
                <button onclick="closeModal('addModal')" style="background: none; border: none; color: #f8f8f2; font-size: 1.5rem; cursor: pointer;">×</button>
            </div>
            
            <form id="addForm">
                <div class="input-group">
                    <label for="addName">ชื่อ-นามสกุล (Text):</label>
                    <input type="text" id="addName" required>
                </div>
                <div class="input-group">
                    <label for="addEmail">อีเมล (Email):</label>
                    <input type="email" id="addEmail" required>
                </div>
                <div class="input-group">
                    <label for="addAge">อายุ (Number):</label>
                    <input type="number" id="addAge" min="18" max="100" required>
                </div>
                <div class="input-group">
                    <label for="addBirthDate">วันเกิด (Date):</label>
                    <input type="date" id="addBirthDate" required>
                </div>
                <div class="input-group">
                    <label for="addPosition">ตำแหน่ง (Select):</label>
                    <select id="addPosition" required>
                        <option value="">-- เลือกตำแหน่ง --</option>
                        <option value="Developer">Developer</option>
                        <option value="Designer">Designer</option>
                        <option value="Manager">Manager</option>
                    </select>
                </div>
                <div class="input-group">
                    <label>เพศ (Radio):</label>
                    <div style="display: flex; gap: 20px;">
                        <div class="inline-group">
                            <input type="radio" id="addGenderMale" name="addGender" value="Male" checked required>
                            <label for="addGenderMale">ชาย</label>
                        </div>
                        <div class="inline-group">
                            <input type="radio" id="addGenderFemale" name="addGender" value="Female">
                            <label for="addGenderFemale">หญิง</label>
                        </div>
                    </div>
                </div>
                <div class="input-group">
                    <label for="addFavColor">สีโปรด (Color):</label>
                    <input type="color" id="addFavColor" value="#00ffff">
                </div>
                <div class="input-group inline-group">
                    <input type="checkbox" id="addIsActive" checked>
                    <label for="addIsActive">สถานะ: ใช้งานระบบ (Checkbox/Boolean)</label>
                </div>
                <div style="margin-top: 20px;">
                    <button type="submit" class="action-button" style="background-color: lightgreen; color: #333;">บันทึก (เพิ่มข้อมูล)</button>
                    <button type="button" onclick="closeModal('addModal')" class="action-button" style="background-color: #777; color: #fff;">ยกเลิก</button>
                </div>
            </form>
        </div>
    </div>

    <div id="editModal" class="simple-modal-backdrop">
        <div class="simple-modal-content">
            <div class="simple-modal-header">
                <h3 style="color:#00ffff;">แก้ไขข้อมูลผู้ใช้ (UPDATE)</h3>
                <button onclick="closeModal('editModal')" style="background: none; border: none; color: #f8f8f2; font-size: 1.5rem; cursor: pointer;">×</button>
            </div>
            
            <form id="editForm">
                <input type="hidden" id="editRecordId"> <div class="input-group">
                    <label for="editName">ชื่อ-นามสกุล (Text):</label>
                    <input type="text" id="editName" required>
                </div>
                <div class="input-group">
                    <label for="editEmail">อีเมล (Email):</label>
                    <input type="email" id="editEmail" required>
                </div>
                <div class="input-group">
                    <label for="editAge">อายุ (Number):</label>
                    <input type="number" id="editAge" min="18" max="100" required>
                </div>
                <div class="input-group">
                    <label for="editBirthDate">วันเกิด (Date):</label>
                    <input type="date" id="editBirthDate" required>
                </div>
                <div class="input-group">
                    <label for="editPosition">ตำแหน่ง (Select):</label>
                    <select id="editPosition" required>
                        <option value="">-- เลือกตำแหน่ง --</option>
                        <option value="Developer">Developer</option>
                        <option value="Designer">Designer</option>
                        <option value="Manager">Manager</option>
                    </select>
                </div>
                <div class="input-group">
                    <label>เพศ (Radio):</label>
                    <div style="display: flex; gap: 20px;">
                        <div class="inline-group">
                            <input type="radio" id="editGenderMale" name="editGender" value="Male" required>
                            <label for="editGenderMale">ชาย</label>
                        </div>
                        <div class="inline-group">
                            <input type="radio" id="editGenderFemale" name="editGender" value="Female">
                            <label for="editGenderFemale">หญิง</label>
                        </div>
                    </div>
                </div>
                <div class="input-group">
                    <label for="editFavColor">สีโปรด (Color):</label>
                    <input type="color" id="editFavColor" value="#00ffff">
                </div>
                <div class="input-group inline-group">
                    <input type="checkbox" id="editIsActive">
                    <label for="editIsActive">สถานะ: ใช้งานระบบ (Checkbox/Boolean)</label>
                </div>
                <div style="margin-top: 20px;">
                    <button type="submit" class="action-button" style="background-color: #00ffff; color: #333;">อัปเดตข้อมูล</button>
                    <button type="button" id="deleteBtnTrigger" class="action-button" style="background-color: red; color: #fff;">ลบข้อมูล</button>
                    <button type="button" onclick="closeModal('editModal')" class="action-button" style="background-color: #777; color: #fff;">ยกเลิก</button>
                </div>
            </form>
        </div>
    </div>

    <div id="deleteConfirmModal" class="simple-modal-backdrop">
        <div class="simple-modal-content">
            <div class="simple-modal-header">
                <h3 style="color:red;">⚠️ ยืนยันการลบข้อมูล</h3>
                <button onclick="closeModal('deleteConfirmModal')" style="background: none; border: none; color: #f8f8f2; font-size: 1.5rem; cursor: pointer;">×</button>
            </div>
            
            <p>คุณต้องการลบข้อมูล ID: <strong id="deleteRecordIdDisplay" style="color: yellow;"></strong> (ชื่อ: <strong id="deleteRecordNameDisplay" style="color: yellow;"></strong>) นี้จริงหรือไม่?</p>
            <input type="hidden" id="deleteRecordId">
            
            <div style="margin-top: 20px;">
                <button type="button" id="confirmDeleteBtn" class="action-button" style="background-color: red; color: #fff;">ยืนยันการลบ</button>
                <button type="button" onclick="closeModal('deleteConfirmModal')" class="action-button" style="background-color: #777; color: #fff;">ยกเลิก</button>
            </div>
        </div>
    </div>
    
    <div class="rocket">🚀</div>

    <script type="text/javascript">
        // โหลดข้อมูลเริ่มต้นจาก PHP Array มาเป็น JavaScript Array
        let simulatedDB = <?php echo json_encode($simulatedDB_php); ?>;
        let nextId = <?php echo $simulatedDB_php[count($simulatedDB_php)-1]['id'] + 1; ?>;

        // 1. ฟังก์ชันปิด Modal ทั่วไป
        function closeModal(modalId) {
            const modal = document.getElementById(modalId);
            if(modal) {
                modal.classList.remove('show');
                modal.style.display = 'none';
            }
            document.getElementById('messageArea').textContent = '';
        }

        // 2. ฟังก์ชันเปิด Modal ทั่วไป (พร้อม animation)
        function openModal(modalId) {
            const modal = document.getElementById(modalId);
            if(modal) {
                modal.style.display = 'flex';
                // Force reflow for transition
                setTimeout(() => modal.classList.add('show'), 10);
            }
        }
        
        // 3. ฟังก์ชันแสดงข้อมูลในตาราง (Simulated SELECT/READ)
        function renderTable(data) {
            const dataBody = document.getElementById('dataBody');
            dataBody.innerHTML = ''; // เคลียร์ข้อมูลเดิม
            
            if (data.length === 0) {
                dataBody.innerHTML = '<tr><td colspan="8" style="text-align: center;">ไม่มีข้อมูลในระบบ</td></tr>';
                return;
            }

            // สร้างตารางใหม่ทั้งหมดด้วย JS
            data.forEach(record => {
                const row = dataBody.insertRow();
                row.className = 'edit-row-trigger'; // ใส่ class เหมือนที่ PHP เคยใส่
                row.setAttribute('data-record-id', record.id);
                
                const isActiveBadge = record.isActive
                    ? `<span class="status-badge" style="background-color: lightgreen; color: #333;">ใช้งาน</span>`
                    : `<span class="status-badge" style="background-color: red; color: white;">ไม่ใช้งาน</span>`;
                
                const colorHtml = `<span class="color-display" style="background-color: ${record.favColor};"></span>`;

                row.innerHTML = `
                    <td>${record.id}</td>
                    <td>${record.name}</td>
                    <td>${record.age}</td>
                    <td>${record.birthDate}</td>
                    <td>${record.position}</td>
                    <td>${record.gender}</td>
                    <td>${colorHtml} ${record.favColor}</td>
                    <td>${isActiveBadge}</td>
                `;
            });
            // ต้องแนบ Event Listener กับแถวใหม่ที่สร้างขึ้น
            attachEditListeners(); 
        }

        // 4. ฟังก์ชันจัดการ Form Submit (Insert/Update)
        function handleFormSubmit(e, actionType) {
            e.preventDefault();
            const formId = e.target.id;
            const isInsert = (actionType === 'INSERT');
            
            let idValue = isInsert ? null : document.getElementById('editRecordId').value;
            let formPrefix = isInsert ? 'add' : 'edit';
            
            // ใช้ formPrefix ในการดึงค่าจาก element ที่ถูกแยก ID
            const selectedGender = document.querySelector(`input[name="${formPrefix}Gender"]:checked`);

            const data = {
                id: idValue ? parseInt(idValue) : null,
                name: document.getElementById(`${formPrefix}Name`).value,
                email: document.getElementById(`${formPrefix}Email`).value,
                age: document.getElementById(`${formPrefix}Age`).value,
                birthDate: document.getElementById(`${formPrefix}BirthDate`).value,
                position: document.getElementById(`${formPrefix}Position`).value,
                gender: selectedGender ? selectedGender.value : null,
                favColor: document.getElementById(`${formPrefix}FavColor`).value,
                isActive: document.getElementById(`${formPrefix}IsActive`).checked
            };
            
            simulateSave(data, actionType, isInsert ? 'addModal' : 'editModal');
        }
        
        // 5. ฟังก์ชันจำลองการบันทึก (Simulated INSERT/UPDATE)
        function simulateSave(data, action, modalId) {
            let message = '';
            data.age = parseInt(data.age);

            if (action === 'INSERT') {
                data.id = nextId++;
                simulatedDB.push(data);
                message = `✅ INSERT สำเร็จ: ID ${data.id}`;
            } else {
                const index = simulatedDB.findIndex(r => r.id == data.id);
                if (index !== -1) {
                    simulatedDB[index] = data;
                    message = `✅ UPDATE สำเร็จ: ID ${data.id}`;
                }
            }
            
            closeModal(modalId);
            document.getElementById('messageArea').textContent = message;
            renderTable(simulatedDB); // โหลดข้อมูลใหม่ (ใช้ JS DOM)
        }
        
        // 6. ฟังก์ชันจำลองการลบ (Simulated DELETE)
        function simulateDelete() {
            const idToDelete = document.getElementById('deleteRecordId').value;
            const initialLength = simulatedDB.length;
            simulatedDB = simulatedDB.filter(r => r.id != idToDelete);
            
            let message = '';
            if (simulatedDB.length < initialLength) {
                message = `❌ DELETE สำเร็จ: ID ${idToDelete} ถูกลบแล้ว`;
            }
            
            closeModal('deleteConfirmModal');
            document.getElementById('messageArea').textContent = message;
            renderTable(simulatedDB); // โหลดข้อมูลใหม่ (ใช้ JS DOM)
        }
        
        // 7. ฟังก์ชันสำหรับเปิด Edit Modal พร้อม Pre-fill
        function openEditModal(record) {
            document.getElementById('editRecordId').value = record.id;
            document.getElementById('editName').value = record.name;
            document.getElementById('editEmail').value = record.email;
            document.getElementById('editAge').value = record.age;
            document.getElementById('editBirthDate').value = record.birthDate;
            document.getElementById('editFavColor').value = record.favColor;
            document.getElementById('editPosition').value = record.position;
            
            const genderRadios = document.getElementsByName('editGender');
            for (const radio of genderRadios) {
                radio.checked = (radio.value === record.gender);
            }

            document.getElementById('editIsActive').checked = record.isActive;
            
            openModal('editModal');
        }
        
        // 8. ฟังก์ชันแนบ Event Listener กับแถวในตาราง
        function attachEditListeners() {
            const rows = document.querySelectorAll('#dataBody tr.edit-row-trigger');
            rows.forEach(row => {
                // ต้องลบ Listener เก่าก่อนเพื่อป้องกันการซ้ำซ้อนหลัง renderTable
                row.removeEventListener('click', handleRowClick);
                row.addEventListener('click', handleRowClick);
            });
        }

        // 9. Handler สำหรับคลิกแถวในตาราง
        function handleRowClick() {
            const recordId = this.getAttribute('data-record-id');
            const record = simulatedDB.find(r => r.id == recordId);
            
            if (record) {
                openEditModal(record);
            }
        }
        
        // ==========================================================
        // Event Listeners
        // ==========================================================
        document.addEventListener('DOMContentLoaded', function() {
            
            // A. Attach Listeners สำหรับแถวที่ถูกสร้างโดย PHP (Initial load)
            attachEditListeners();
            
            // B. Add New Button (เปิด Add Modal)
            document.getElementById('addNewBtn').addEventListener('click', function() {
                document.getElementById('addForm').reset();
                document.getElementById('addGenderMale').checked = true; // Set default radio
                document.getElementById('addIsActive').checked = true; // Set default checkbox
                document.getElementById('addFavColor').value = '#00ffff'; // Set default color
                openModal('addModal');
            });

            // C. Form Submit (Insert)
            document.getElementById('addForm').addEventListener('submit', function(e) {
                handleFormSubmit(e, 'INSERT');
            });
            
            // D. Form Submit (Update)
            document.getElementById('editForm').addEventListener('submit', function(e) {
                handleFormSubmit(e, 'UPDATE');
            });
            
            // E. Delete Button Trigger (ใน Edit Modal) -> เปิด Confirm Delete Modal
            document.getElementById('deleteBtnTrigger').addEventListener('click', function() {
                const idToDelete = document.getElementById('editRecordId').value;
                const record = simulatedDB.find(r => r.id == idToDelete);

                closeModal('editModal');
                
                document.getElementById('deleteRecordId').value = idToDelete;
                document.getElementById('deleteRecordIdDisplay').textContent = idToDelete;
                document.getElementById('deleteRecordNameDisplay').textContent = record ? record.name : 'N/A';
                
                openModal('deleteConfirmModal');
            });
            
            // F. Confirm Delete Button (ใน Delete Modal) -> สั่งลบ
            document.getElementById('confirmDeleteBtn').addEventListener('click', function() {
                simulateDelete();
            });

            // G. Rocket animation
            const rocket = document.querySelector('.rocket');
            if (rocket) {
                rocket.style.animationPlayState = 'running';
            }
        });
    </script> 
                    

เพิ่มข้อมูลผู้ใช้ใหม่ (INSERT)

แก้ไขข้อมูลผู้ใช้ (UPDATE)

⚠️ ยืนยันการลบข้อมูล

คุณต้องการลบข้อมูล ID: (ชื่อ: ) นี้จริงหรือไม่?

🚀