Bootstrap 5
Datatable
Table
Template
Filter Table
Dashboard
Table avec Datatable optimisée pour la visualisation et l'interaction. Design moderne et responsive.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<meta name="copyright" content="MEZGANI Said" />
<meta name="author" content="AngularForAll" />
<meta name="robots" content="noindex, nofollow" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Snippet Datatable Bootstrap 5 2026 230400337 | AngularForAll</title>
<!-- Bootstrap 5 -->
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/css/bootstrap.min.css" rel="stylesheet">
<!-- DataTables Bootstrap 5 -->
<link href="https://cdn.datatables.net/1.13.7/css/dataTables.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/buttons/2.4.2/css/buttons.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/select/1.7.0/css/select.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/searchpanes/2.2.0/css/searchPanes.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/searchbuilder/1.6.0/css/searchBuilder.bootstrap5.min.css" rel="stylesheet">
<link href="https://cdn.datatables.net/datetime/1.5.1/css/dataTables.dateTime.min.css" rel="stylesheet">
<!-- Font Awesome pour les icônes -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css">
<style>
body {
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
min-height: 100vh;
padding: 2rem 0;
font-family: 'Inter', system-ui, sans-serif;
}
.container-custom {
background: white;
border-radius: 20px;
padding: 2rem;
box-shadow: 0 20px 60px rgba(0,0,0,0.2);
}
h1 {
background: linear-gradient(135deg, #667eea, #764ba2);
-webkit-background-clip: text;
-webkit-text-fill-color: transparent;
font-weight: 700;
}
.table-container {
overflow-x: auto;
}
/* Styles personnalisés pour DataTables */
.dt-buttons {
margin-bottom: 1rem;
}
.dt-button {
background: linear-gradient(135deg, #667eea, #764ba2) !important;
color: white !important;
border: none !important;
border-radius: 8px !important;
padding: 8px 16px !important;
margin-right: 8px !important;
font-weight: 500 !important;
transition: all 0.3s !important;
}
.dt-button:hover {
transform: translateY(-2px) !important;
box-shadow: 0 4px 12px rgba(102, 126, 234, 0.4) !important;
}
.dataTables_filter input {
border-radius: 8px !important;
border: 2px solid #e0e0e0 !important;
padding: 8px 16px !important;
margin-left: 8px !important;
}
.dataTables_filter input:focus {
border-color: #667eea !important;
outline: none !important;
box-shadow: 0 0 0 3px rgba(102, 126, 234, 0.1) !important;
}
.dataTables_length select {
border-radius: 8px !important;
border: 2px solid #e0e0e0 !important;
padding: 6px 12px !important;
}
.page-item.active .page-link {
background: linear-gradient(135deg, #667eea, #764ba2) !important;
border-color: #667eea !important;
}
.page-link {
color: #667eea !important;
border-radius: 8px !important;
margin: 0 4px !important;
}
.page-link:hover {
background: #f3f4f6 !important;
}
table.dataTable thead th {
background: #f8f9fa;
font-weight: 600;
border-bottom: 2px solid #dee2e6;
}
.badge-status {
padding: 6px 12px;
border-radius: 20px;
font-weight: 500;
font-size: 12px;
}
.status-active {
background: #d1fae5;
color: #065f46;
}
.status-inactive {
background: #fee2e2;
color: #991b1b;
}
.status-pending {
background: #fef3c7;
color: #92400e;
}
.stats-card {
background: linear-gradient(135deg, #667eea, #764ba2);
color: white;
border-radius: 16px;
padding: 1.5rem;
margin-bottom: 2rem;
}
.stats-number {
font-size: 2.5rem;
font-weight: 700;
}
.btn-action {
padding: 4px 10px;
border-radius: 6px;
margin: 0 4px;
transition: all 0.2s;
}
.btn-action:hover {
transform: scale(1.1);
}
</style>
</head>
<body>
<div class="container">
<!-- Header -->
<div class="text-center mb-4">
<h1 class="display-4 mb-3">
<i class="fas fa-table me-3" style="background: linear-gradient(135deg, #667eea, #764ba2); -webkit-background-clip: text; -webkit-text-fill-color: transparent;"></i>
DataTable Bootstrap 5
</h1>
<p class="lead text-white-50">Gestion avancée avec recherche, filtres, pagination, tri et export</p>
</div>
<!-- Container principal -->
<div class="container-custom">
<!-- Statistiques -->
<div class="row mb-4">
<div class="col-md-4 mb-3">
<div class="stats-card">
<i class="fas fa-users fa-2x mb-2"></i>
<div class="stats-number" id="totalRecords">0</div>
<div>Total enregistrements</div>
</div>
</div>
<div class="col-md-4 mb-3">
<div class="stats-card" style="background: linear-gradient(135deg, #f59e0b, #ef4444);">
<i class="fas fa-filter fa-2x mb-2"></i>
<div class="stats-number" id="filteredRecords">0</div>
<div>Enregistrements filtrés</div>
</div>
</div>
<div class="col-md-4 mb-3">
<div class="stats-card" style="background: linear-gradient(135deg, #10b981, #059669);">
<i class="fas fa-database fa-2x mb-2"></i>
<div class="stats-number" id="activeFilters">0</div>
<div>Filtres actifs</div>
</div>
</div>
</div>
<!-- Filtres rapides -->
<div class="row mb-4">
<div class="col-12">
<div class="d-flex flex-wrap gap-2">
<button class="btn btn-outline-primary filter-quick" data-status="all">
<i class="fas fa-list me-2"></i>Tous
</button>
<button class="btn btn-outline-success filter-quick" data-status="Actif">
<i class="fas fa-check-circle me-2"></i>Actifs
</button>
<button class="btn btn-outline-warning filter-quick" data-status="En attente">
<i class="fas fa-clock me-2"></i>En attente
</button>
<button class="btn btn-outline-danger filter-quick" data-status="Inactif">
<i class="fas fa-times-circle me-2"></i>Inactifs
</button>
</div>
</div>
</div>
<!-- Table -->
<div class="table-container">
<table id="mainTable" class="table table-striped table-hover" style="width:100%">
<thead>
<tr>
<th>ID</th>
<th>Nom complet</th>
<th>Email</th>
<th>Téléphone</th>
<th>Département</th>
<th>Poste</th>
<th>Date d'embauche</th>
<th>Salaire (€)</th>
<th>Statut</th>
<th>Actions</th>
</tr>
</thead>
<tbody id="tableBody">
<!-- Les données seront injectées ici -->
</tbody>
<tfoot>
<tr>
<th>ID</th>
<th>Nom complet</th>
<th>Email</th>
<th>Téléphone</th>
<th>Département</th>
<th>Poste</th>
<th>Date d'embauche</th>
<th>Salaire (€)</th>
<th>Statut</th>
<th>Actions</th>
</tr>
</tfoot>
</table>
</div>
<!-- Légende -->
<div class="mt-4 p-3 bg-light rounded-3">
<h6 class="mb-3"><i class="fas fa-info-circle me-2"></i>Fonctionnalités disponibles :</h6>
<div class="row">
<div class="col-md-3">
<i class="fas fa-search text-primary me-2"></i>Recherche globale
</div>
<div class="col-md-3">
<i class="fas fa-filter text-success me-2"></i>Filtres par colonne
</div>
<div class="col-md-3">
<i class="fas fa-sort text-warning me-2"></i>Tri multi-colonnes
</div>
<div class="col-md-3">
<i class="fas fa-file-export text-info me-2"></i>Export (CSV, Excel, PDF)
</div>
</div>
</div>
</div>
</div>
<!-- Scripts -->
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.2/dist/js/bootstrap.bundle.min.js"></script>
<!-- DataTables -->
<script src="https://cdn.datatables.net/1.13.7/js/jquery.dataTables.min.js"></script>
<script src="https://cdn.datatables.net/1.13.7/js/dataTables.bootstrap5.min.js"></script>
<!-- Extensions DataTables -->
<script src="https://cdn.datatables.net/buttons/2.4.2/js/dataTables.buttons.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.bootstrap5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.html5.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.print.min.js"></script>
<script src="https://cdn.datatables.net/buttons/2.4.2/js/buttons.colVis.min.js"></script>
<script src="https://cdn.datatables.net/select/1.7.0/js/dataTables.select.min.js"></script>
<script src="https://cdn.datatables.net/searchpanes/2.2.0/js/dataTables.searchPanes.min.js"></script>
<script src="https://cdn.datatables.net/searchpanes/2.2.0/js/searchPanes.bootstrap5.min.js"></script>
<script src="https://cdn.datatables.net/searchbuilder/1.6.0/js/dataTables.searchBuilder.min.js"></script>
<script src="https://cdn.datatables.net/searchbuilder/1.6.0/js/searchBuilder.bootstrap5.min.js"></script>
<script src="https://cdn.datatables.net/datetime/1.5.1/js/dataTables.dateTime.min.js"></script>
<!-- JSZip pour export Excel -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
<!-- PDFMake pour export PDF -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/pdfmake.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/pdfmake/0.2.7/vfs_fonts.js"></script>
<script>
// Données de démonstration (100 enregistrements)
const demoData = [];
const firstNames = ['Jean', 'Marie', 'Pierre', 'Sophie', 'Thomas', 'Julie', 'Nicolas', 'Emma', 'Lucas', 'Léa', 'Antoine', 'Camille', 'Paul', 'Sarah', 'David', 'Claire', 'Michel', 'Céline', 'François', 'Isabelle'];
const lastNames = ['Martin', 'Bernard', 'Dubois', 'Thomas', 'Robert', 'Richard', 'Petit', 'Durand', 'Leroy', 'Moreau', 'Simon', 'Laurent', 'Lefebvre', 'Michel', 'Garcia', 'David', 'Bertrand', 'Roux', 'Vincent', 'Fournier'];
const departments = ['Informatique', 'Marketing', 'Ressources Humaines', 'Finance', 'Commercial', 'Production', 'R&D', 'Service Client', 'Logistique', 'Direction'];
const positions = {
'Informatique': ['Développeur', 'Admin Système', 'Chef de projet', 'Architecte', 'DevOps'],
'Marketing': ['Community Manager', 'SEO Manager', 'Growth Hacker', 'Brand Manager', 'Traffic Manager'],
'Ressources Humaines': ['Recruteur', 'HRBP', 'Formateur', 'Payroll', 'Talent Acquisition'],
'Finance': ['Comptable', 'Contrôleur', 'Auditeur', 'Trésorier', 'Analyste Financier'],
'Commercial': ['Commercial', 'Account Manager', 'Sales Dev', 'Key Account', 'Business Dev'],
'Production': ['Opérateur', 'Chef d\'équipe', 'Responsable Qualité', 'Technicien', 'Superviseur'],
'R&D': ['Chercheur', 'Ingénieur R&D', 'Scientifique', 'Lab Manager', 'Innovation Manager'],
'Service Client': ['Conseiller', 'Superviseur', 'Quality Analyst', 'Team Leader', 'Support Tech'],
'Logistique': ['Magasinier', 'Responsable Logistique', 'Planificateur', 'Gestionnaire Stock', 'Transport Manager'],
'Direction': ['Directeur', 'Directeur Adjoint', 'Secrétaire Général', 'Chief of Staff', 'Executive Assistant']
};
const statuses = ['Actif', 'Inactif', 'En attente'];
// Génération des données
for (let i = 1; i <= 100; i++) {
const firstName = firstNames[Math.floor(Math.random() * firstNames.length)];
const lastName = lastNames[Math.floor(Math.random() * lastNames.length)];
const department = departments[Math.floor(Math.random() * departments.length)];
const position = positions[department][Math.floor(Math.random() * positions[department].length)];
const status = statuses[Math.floor(Math.random() * statuses.length)];
// Date d'embauche aléatoire (entre 2015 et 2024)
const hireDate = new Date(2015 + Math.floor(Math.random() * 10), Math.floor(Math.random() * 12), Math.floor(Math.random() * 28) + 1);
const hireDateStr = hireDate.toLocaleDateString('fr-FR');
// Salaire entre 25000 et 120000
const salary = Math.floor(Math.random() * 95000) + 25000;
demoData.push({
id: i,
name: `${firstName} ${lastName}`,
email: `${firstName.toLowerCase()}.${lastName.toLowerCase()}@entreprise.com`,
phone: `06 ${Math.floor(Math.random() * 90 + 10)} ${Math.floor(Math.random() * 90 + 10)} ${Math.floor(Math.random() * 90 + 10)} ${Math.floor(Math.random() * 90 + 10)}`,
department: department,
position: position,
hireDate: hireDateStr,
salary: salary,
status: status
});
}
// Tri par ID
demoData.sort((a, b) => a.id - b.id);
// Remplissage du tableau
const tbody = document.getElementById('tableBody');
demoData.forEach(item => {
const row = document.createElement('tr');
let statusClass = '';
if (item.status === 'Actif') statusClass = 'status-active';
else if (item.status === 'Inactif') statusClass = 'status-inactive';
else statusClass = 'status-pending';
row.innerHTML = `
<td>${item.id}</td>
<td><i class="fas fa-user me-2 text-primary"></i>${item.name}</td>
<td><i class="fas fa-envelope me-2 text-secondary"></i>${item.email}</td>
<td><i class="fas fa-phone me-2 text-success"></i>${item.phone}</td>
<td><span class="badge bg-info">${item.department}</span></td>
<td>${item.position}</td>
<td><i class="fas fa-calendar me-2 text-warning"></i>${item.hireDate}</td>
<td class="text-end fw-semibold">${item.salary.toLocaleString('fr-FR')} €</td>
<td><span class="badge-status ${statusClass}">${item.status}</span></td>
<td>
<button class="btn btn-sm btn-outline-primary btn-action" onclick="viewItem(${item.id})" title="Voir">
<i class="fas fa-eye"></i>
</button>
<button class="btn btn-sm btn-outline-warning btn-action" onclick="editItem(${item.id})" title="Modifier">
<i class="fas fa-edit"></i>
</button>
<button class="btn btn-sm btn-outline-danger btn-action" onclick="deleteItem(${item.id})" title="Supprimer">
<i class="fas fa-trash"></i>
</button>
</td>
`;
tbody.appendChild(row);
});
// Initialisation de DataTable avec toutes les fonctionnalités
$(document).ready(function() {
const table = $('#mainTable').DataTable({
// Pagination
pageLength: 10,
lengthMenu: [[5, 10, 25, 50, 100, -1], [5, 10, 25, 50, 100, "Tous"]],
// Recherche
searching: true,
// Tri
ordering: true,
// Informations
info: true,
// État de sauvegarde
stateSave: true,
// Langue française
language: {
url: 'https://cdn.datatables.net/plug-ins/1.13.7/i18n/fr-FR.json'
},
// Extensions activées
layout: {
topStart: {
buttons: [
{
extend: 'copy',
text: '<i class="fas fa-copy me-1"></i>Copier',
className: 'btn-sm'
},
{
extend: 'csv',
text: '<i class="fas fa-file-csv me-1"></i>CSV',
className: 'btn-sm'
},
{
extend: 'excel',
text: '<i class="fas fa-file-excel me-1"></i>Excel',
className: 'btn-sm'
},
{
extend: 'pdf',
text: '<i class="fas fa-file-pdf me-1"></i>PDF',
className: 'btn-sm',
orientation: 'landscape',
pageSize: 'A4',
exportOptions: {
columns: [0, 1, 2, 4, 5, 6, 7, 8]
}
},
{
extend: 'print',
text: '<i class="fas fa-print me-1"></i>Imprimer',
className: 'btn-sm'
},
{
extend: 'colvis',
text: '<i class="fas fa-columns me-1"></i>Colonnes',
className: 'btn-sm'
}
]
},
topEnd: {
search: {
placeholder: 'Rechercher...'
}
}
},
// Configuration des colonnes
columnDefs: [
{
targets: [8], // Colonne Statut
searchPanes: {
show: true
}
},
{
targets: [4], // Colonne Département
searchPanes: {
show: true
}
},
{
targets: [6], // Colonne Date
type: 'date'
},
{
targets: [7], // Colonne Salaire
type: 'num'
},
{
targets: [9], // Colonne Actions (non triable)
orderable: false,
searchable: false
}
],
// SearchPanes configuration
searchPanes: {
cascadePanes: true,
viewTotal: true,
layout: 'columns-4'
},
// Select extension
select: {
style: 'multi',
selector: 'td:not(:last-child)'
},
// Responsive
responsive: true,
// AutoWidth
autoWidth: true,
// Scroll horizontal
scrollX: true,
// Initialisation terminée
initComplete: function() {
// Mise à jour des statistiques
updateStats(this);
// Écouteur pour mise à jour des stats
this.on('search.dt order.dt page.dt length.dt', function() {
updateStats(this);
});
}
});
// Filtres rapides
$('.filter-quick').on('click', function() {
const status = $(this).data('status');
if (status === 'all') {
table.column(8).search('').draw();
} else {
table.column(8).search(status).draw();
}
// Style actif
$('.filter-quick').removeClass('active');
$(this).addClass('active');
});
// Fonction de mise à jour des statistiques
function updateStats(dataTable) {
const info = dataTable.page.info();
$('#totalRecords').text(info.recordsTotal);
$('#filteredRecords').text(info.recordsDisplay);
// Compter les filtres actifs
let activeFilterCount = 0;
const settings = dataTable.settings()[0];
if (settings.oPreviousSearch.sSearch) activeFilterCount++;
settings.aoPreSearchCols.forEach(col => {
if (col.sSearch) activeFilterCount++;
});
$('#activeFilters').text(activeFilterCount);
}
// Exposer la table globalement
window.dataTable = table;
});
// Fonctions d'action
function viewItem(id) {
const item = demoData.find(d => d.id === id);
alert(`👤 ${item.name}\n📧 ${item.email}\n💼 ${item.position}\n🏢 ${item.department}\n💰 ${item.salary.toLocaleString('fr-FR')} €`);
}
function editItem(id) {
const item = demoData.find(d => d.id === id);
alert(`✏️ Modification de ${item.name}`);
}
function deleteItem(id) {
const item = demoData.find(d => d.id === id);
if (confirm(`⚠️ Supprimer ${item.name} ?`)) {
alert(`✅ ${item.name} supprimé`);
}
}
</script>
</body>
</html>
Ouvrir cet aperçu dans un nouvel onglet du navigateur
🔗 Ouvrir dans le navigateur