I'm working on a website that is basically a CRUD. Since it's hosted on a managed server, I'm using HTML, Tailwind CSS/JS, Flowbite CSS/JS, jQuery with AJAX and PHP. Here's the structure of my page with all the appropriate references:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My Page</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/flowbite@2.4.1/dist/flowbite.min.css" rel="stylesheet" />
</head>
<body class="customers">
<!-- Table with data -->
<div class="relative overflow-x-auto rounded-lg">
<table id="CustomersTable" class="min-w-full text-sm text-left rtl:text-right text-black">
<thead class="text-xs text-center uppercase bg-gray-200">
<tr>
<th scope="col" class="border-r border-gray-400 px-6 py-3">
Name
</th>
<th scope="col" class="border-r border-gray-400 px-6 py-3">
Web
</th>
<th scope="col" class="border-r border-gray-400 px-6 py-3">
Email
</th>
</tr>
</thead>
<tbody>
</tbody>
</table>
</div>
<!-- Main modal -->
<div id="customer_modal" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-4xl max-h-full">
<!-- Modal content -->
<div class="relative bg-white rounded-lg shadow">
<!-- Modal header -->
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t">
<button type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center" data-modal-toggle="customer_modal">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6"/>
</svg>
<span class="sr-only">Close modal</span>
</button>
</div>
<!-- Modal body -->
<form class="p-4 md:p-5">
<div class="grid gap-4 mb-4 grid-cols-2">
<div>
<label for="name" class="block mb-2 text-sm font-medium text-black">Name</label>
<input type="text" id="name" class="bg-gray-50 border border-gray-300 text-black text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required />
</div>
<div>
<label for="web" class="block mb-2 text-sm font-medium text-black">Web</label>
<input type="text" id="web" class="bg-gray-50 border border-gray-300 text-black text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required />
</div>
<div>
<label for="email" class="block mb-2 text-sm font-medium text-black">Email</label>
<input type="email" id="email" class="bg-gray-50 border border-gray-300 text-black text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required />
</div>
<button type="submit" class="text-white inline-flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center">
Save
</button>
</form>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flowbite@2.4.1/dist/flowbite.min.js"></script>
<script src="/scripts/app.js"></script>
</body>
</html>
I dynamically populate the table body based on the response from the server using jQuery and AJAX using the following code:
$(document).ready(function() {
if ($('body').hasClass('customers')) {
fetchCustomers();
function fetchCustomers() {
let requestData = {
action: "CustomerTable"
};
$.ajax({
url: '/customers',
type: 'POST',
data: requestData,
dataType: 'json',
success: function(response) {
let tableBody = $('#CustomersTable tbody');
tableBody.empty();
response.forEach(function(customer) {
let row = $('<tr class="odd:bg-white even:bg-gray-100 border-b hover:bg-gray-200 whitespace-nowrap"></tr>');
row.append($('<td class="px-6 py-4" data-modal-target="customer_modal" data-modal-show="customer_modal"></td>').text(customer.name));
row.append($('<td class="px-6 py-4"></td>').text(customer.web));
row.append($('<td class="px-6 py-4"></td>').text(customer.email));
tableBody.append(row);
});
}
});
}
}
});
This works great. However, I'd also like to allow the user to click on any row of the column Name
and open the modal form included in my HTML code. For this, the jQuery code adds the attributes data-modal-target="customer_modal" data-modal-show="customer_modal"
to each customer name on the table. However, since this happens after the page is loaded, Flowbite doesn't recognize the new data-* attributes and nothing happens.
I've searched the documentation and found that you can reinitialize Flowbite to properly identify all data attributes after the page has loaded (Tailwind CSS JavaScript - Flowbite). I'm supposed to just do something like initFlowbite();
at the end of my JavaScript code. Unfortunately, when trying to do so the problem persists and I get a console log saying that initFlowbite();
is not defined. I believe the code import { initFlowbite } from 'flowbite'
is only compatible when you are working with modules and have access to the command line of the server.
Could anyone please help me fix this problem? I greatly appreciate any suggestions to be able to successfully reinitialize Flowbite event handlers whenever needed based on my current set up.
The initFlowbite()
function is available on the window
namespace, which means you can call it like initFlowbite()
or as a method on the window
object like window.initFlowbite()
:
$(document).ready(function() {
if ($('body').hasClass('customers')) {
fetchCustomers();
function fetchCustomers() {
setTimeout(function success() {
const response = [{
name: 'Foo',
web: 'foo',
email: 'foo@example.com',
}, {
name: 'Bar',
web: 'bar',
email: 'bar@example.com',
}]
let tableBody = $('#CustomersTable tbody');
tableBody.empty();
response.forEach(function(customer) {
let row = $('<tr class="odd:bg-white even:bg-gray-100 border-b hover:bg-gray-200 whitespace-nowrap"></tr>');
row.append($('<td class="px-6 py-4" data-modal-target="customer_modal" data-modal-show="customer_modal"></td>').text(customer.name));
row.append($('<td class="px-6 py-4"></td>').text(customer.web));
row.append($('<td class="px-6 py-4"></td>').text(customer.email));
tableBody.append(row);
});
initFlowbite();
}, 100);
}
}
});
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>My Page</title>
<script src="https://cdn.tailwindcss.com"></script>
<link href="https://cdn.jsdelivr.net/npm/flowbite@2.4.1/dist/flowbite.min.css" rel="stylesheet" />
</head>
<body class="customers">
<!-- Table with data -->
<div class="relative overflow-x-auto rounded-lg">
<table id="CustomersTable" class="min-w-full text-sm text-left rtl:text-right text-black">
<thead class="text-xs text-center uppercase bg-gray-200">
<tr>
<th scope="col" class="border-r border-gray-400 px-6 py-3">Name</th>
<th scope="col" class="border-r border-gray-400 px-6 py-3">Web</th>
<th scope="col" class="border-r border-gray-400 px-6 py-3">Email</th>
</tr>
</thead>
<tbody></tbody>
</table>
</div>
<!-- Main modal -->
<div id="customer_modal" tabindex="-1" aria-hidden="true" class="hidden overflow-y-auto overflow-x-hidden fixed top-0 right-0 left-0 z-50 justify-center items-center w-full md:inset-0 h-[calc(100%-1rem)] max-h-full">
<div class="relative p-4 w-full max-w-4xl max-h-full">
<!-- Modal content -->
<div class="relative bg-white rounded-lg shadow">
<!-- Modal header -->
<div class="flex items-center justify-between p-4 md:p-5 border-b rounded-t">
<button type="button" class="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm w-8 h-8 ms-auto inline-flex justify-center items-center" data-modal-toggle="customer_modal">
<svg class="w-3 h-3" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 14 14">
<path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 6 6m0 0 6 6M7 7l6-6M7 7l-6 6" />
</svg>
<span class="sr-only">Close modal</span>
</button>
</div>
<!-- Modal body -->
<form class="p-4 md:p-5">
<div class="grid gap-4 mb-4 grid-cols-2">
<div>
<label for="name" class="block mb-2 text-sm font-medium text-black">Name</label>
<input type="text" id="name" class="bg-gray-50 border border-gray-300 text-black text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required />
</div>
<div>
<label for="web" class="block mb-2 text-sm font-medium text-black">Web</label>
<input type="text" id="web" class="bg-gray-50 border border-gray-300 text-black text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required />
</div>
<div>
<label for="email" class="block mb-2 text-sm font-medium text-black">Email</label>
<input type="email" id="email" class="bg-gray-50 border border-gray-300 text-black text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5" required />
</div>
<button type="submit" class="text-white inline-flex items-center bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center">Save</button>
</div>
</form>
</div>
</div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.7.1/jquery.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/flowbite@2.4.1/dist/flowbite.min.js"></script>
<script src="/scripts/app.js"></script>
</body>
</html>