Building a CRUD Application with CodeIgniter 4.6 , HTMX, and SweetAlert2

 In this tutorial, we’ll build a User Management System using CodeIgniter 4, HTMX for dynamic front-end interactions, and SweetAlert2 for displaying alerts. We’ll use the provided UserModel to handle database operations and create a fully functional CRUD application.


Prerequisites:

  • Basic knowledge of PHP and CodeIgniter 4.

  • Familiarity with HTMX and JavaScript.

  • CodeIgniter 4 installed and configured.


Step 1: Setting Up the UserModel

The UserModel provided is already well-structured. It includes:

  • Table configuration (users).

  • Automatic timestamps for created_at and updated_at.

  • Soft deletes using deleted_at.

  • Validation rules for name and email.

Here’s the UserModel again for reference:

php
Copy
<?php

namespace App\Models;

use CodeIgniter\Model;

class UserModel extends Model{
    protected $table = 'users'; // Table name in the database
    protected $primaryKey = 'id'; // Primary key column name
    protected $useAutoIncrement = true; // Set false if using manual IDs

    protected $allowedFields = ['name', 'email', 'password', 'created_at', 'updated_at', 'deleted_at'];
    
    protected $useTimestamps = true; // Enables automatic timestamps
    protected $createdField = 'created_at'; // Column for created timestamp
    protected $updatedField = 'updated_at'; // Column for updated timestamp

    protected $useSoftDeletes = true; // Enables soft delete
    protected $deletedField = 'deleted_at'; // Column for soft deletes

    protected $validationRules = [
        'name' => 'required|min_length[3]|max_length[255]',
        'email' => 'required|valid_email'
    ];
    
    protected $validationMessages = [
        'name' => [
            'required' => 'Name is required',
            'min_length' => 'Name must have at least 3 characters'
        ]
    ];
}

Step 2: Creating the UserController

Next, let’s create a UserController to handle CRUD operations. We’ll use HTMX to make the front-end dynamic and SweetAlert2 to display success/error messages.

php
Copy
<?php

namespace App\Controllers;

use App\Models\UserModel;
use CodeIgniter\API\ResponseTrait;

class UserController extends BaseController
{
    use ResponseTrait;

    protected $userModel;

    public function __construct()
    {
        $this->userModel = new UserModel();
    }

    // List all users
    public function index()
    {
        $data['users'] = $this->userModel->findAll();
        return view('user_list', $data);
    }

    // Show create form
    public function create()
    {
        return view('user_create');
    }

    // Store a new user
    public function store()
    {
        $data = $this->request->getPost();

        if (!$this->userModel->save($data)) {
            return $this->respond([
                'status' => 'error',
                'errors' => $this->userModel->errors()
            ]);
        }

        return $this->respond([
            'status' => 'success',
            'message' => 'User created successfully!'
        ]);
    }

    // Show edit form
    public function edit($id)
    {
        $data['user'] = $this->userModel->find($id);
        return view('user_edit', $data);
    }

    // Update a user
    public function update($id)
    {
        $data = $this->request->getPost();

        if (!$this->userModel->update($id, $data)) {
            return $this->respond([
                'status' => 'error',
                'errors' => $this->userModel->errors()
            ]);
        }

        return $this->respond([
            'status' => 'success',
            'message' => 'User updated successfully!'
        ]);
    }

    // Delete a user (soft delete)
    public function delete($id)
    {
        $this->userModel->delete($id);

        return $this->respond([
            'status' => 'success',
            'message' => 'User deleted successfully!'
        ]);
    }
}

Step 3: Creating Views with HTMX

We’ll use HTMX to handle form submissions and dynamically update the UI without reloading the page.

user_list.php (List all users)

html
Copy
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>User List</title>
    <script src="https://unpkg.com/htmx.org"></script>
    <script src="https://cdn.jsdelivr.net/npm/sweetalert2@11"></script>
</head>
<body>
    <h1>User List</h1>
    <a href="/users/create" hx-get="/users/create" hx-target="#content">Create User</a>
    <div id="content">
        <table>
            <thead>
                <tr>
                    <th>ID</th>
                    <th>Name</th>
                    <th>Email</th>
                    <th>Actions</th>
                </tr>
            </thead>
            <tbody>
                <?php foreach ($users as $user): ?>
                <tr>
                    <td><?= $user['id'] ?></td>
                    <td><?= $user['name'] ?></td>
                    <td><?= $user['email'] ?></td>
                    <td>
                        <a href="/users/edit/<?= $user['id'] ?>" hx-get="/users/edit/<?= $user['id'] ?>" hx-target="#content">Edit</a>
                        <a href="/users/delete/<?= $user['id'] ?>" hx-delete="/users/delete/<?= $user['id'] ?>">Delete</a>
                    </td>
                </tr>
                <?php endforeach; ?>
            </tbody>
        </table>
    </div>

    <script>
        document.addEventListener('htmx:afterRequest', handleResponse);
        function handleResponse(event) {
            const response = event.detail.xhr.response;

            try {
                const responseData = JSON.parse(response);

                if (responseData.status === 'success') {
                    Swal.fire({
                        icon: 'success',
                        title: 'Success',
                        text: responseData.message,
                    }).then(() => {
                        window.location.reload(); // Reload page after success
                    });
                } else {
                    const errors = responseData.errors || { general: "An unknown error occurred" };
                    let errorMessages = Object.values(errors).map(error => `<p>${error}</p>`).join('');

                    Swal.fire({
                        icon: 'error',
                        title: 'Error',
                        html: errorMessages,
                    });
                }
            } catch (e) {
                Swal.fire({
                    icon: 'error',
                    title: 'Error',
                    text: 'An unexpected error occurred. Please try again.',
                });
                console.error('Error parsing response:', e);
            }
        }
    </script>
</body>
</html>

user_create.php (Create user form)

html
Copy
<div>
    <h2>Create User</h2>
    <form hx-post="/users/store" hx-target="#content">
        <label for="name">Name:</label>
        <input type="text" name="name" required>
        <label for="email">Email:</label>
        <input type="email" name="email" required>
        <button type="submit">Submit</button>
    </form>
</div>

user_edit.php (Edit user form)

html
Copy
<div>
    <h2>Edit User</h2>
    <form hx-post="/users/update/<?= $user['id'] ?>" hx-target="#content">
        <label for="name">Name:</label>
        <input type="text" name="name" value="<?= $user['name'] ?>" required>
        <label for="email">Email:</label>
        <input type="email" name="email" value="<?= $user['email'] ?>" required>
        <button type="submit">Update</button>
    </form>
</div>

Step 4: Testing the Application

  1. Start your CodeIgniter server.

  2. Navigate to /users to see the list of users.

  3. Use the "Create User" link to add a new user.

  4. Edit or delete users using the respective buttons.


Conclusion

In this tutorial, we built a CRUD application using CodeIgniter 4HTMX, and SweetAlert2. This combination allows for a seamless user experience with dynamic updates and beautiful alerts. You can extend this application by adding features like pagination, search, or user authentication.

Happy coding! 🚀

Share:

0 Comments:

Post a Comment