Bootstrap 5 Search Filter Table | Employee Records with Dropdown Filters & JavaScript
Bootstrap 5 Search Filter Table | Employee Records with Dropdown Filters & JavaScript
This Bootstrap 5 Search Filter Table is designed to manage and display employee records through a clean, responsive, and interactive data table interface. The application allows users to search and filter employee data in real time using dropdown filters and search functionality based on Name, Email, Position, Department, and Status — all without page reloads. It also includes dynamic record counters that automatically update Total Records, Visible Records, and Hidden Records as users interact with the table.
Built with Bootstrap 5 and JavaScript, this employee management table demonstrates practical frontend development techniques such as live searching, dropdown filtering, DOM manipulation, event handling, and dynamic data rendering. The project showcases how modern web applications can provide fast, user-friendly data management experiences through responsive UI components, real-time filtering systems, and interactive table functionality
Steps to Create a Bootstrap 5 Search Filter Table with Employee Records
Follow these simple steps to build a Bootstrap 5 Search Filter Table using Bootstrap and JavaScript:
-
Create a folder with any name, for example, bootstrap-search-filter-table.
-
Inside the folder, create necessary files named index.html, style.css, script.js.
In the index.html file, add the basic HTML structure for the employee records table, including a search input field, dropdown filters, live record counters, and a responsive Bootstrap 5 table layout.
Add employee data rows with fields such as Name, Email, Position, Department, and Status inside the table body.
<!DOCTYPE html>
<!-- TheProviders ----------------- youtube.com/@TheProvidersOfficial -->
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Search & Filter Table using Bootstrap 5 & JavaScript</title>
<link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-sRIl4kxILFvY47J16cr9ZwB07vP4J8+LH7qKQnuqkuIAvNWLzeN8tE5YBujZqJLB" crossorigin="anonymous">
<link rel="stylesheet" href="style.css">
</head>
<body>
<div class="container">
<div class="card rounded-4 overflow-hidden border-0">
<div class="card-header p-4 text-white">
<h2>Employees Data</h2>
<p class="mb-0">Search and Filter employees records</p>
</div>
<div class="card-body">
<!-- statistics -->
<div class="row text-center g-0 mb-4 p-3 stats rounded">
<div class="col-md-4">
<div class="number fs-2 fw-bold" id="totalRecords">0</div>
<div class="label">TOTAL RECORDS</div>
</div>
<div class="col-md-4">
<div class="number fs-2 fw-bold" id="visibleRecords">0</div>
<div class="label">VISIBLE RECORDS</div>
</div>
<div class="col-md-4">
<div class="number fs-2 fw-bold" id="hiddenRecords">0</div>
<div class="label">HIDDEN RECORDS</div>
</div>
</div>
</div>
<!-- search & filter section -->
<div class="search-section rounded-3 p-4 mb-4">
<div class="row g-3">
<div class="col-md-5">
<label for="searchInput" class="form-label fw-bold">Search</label>
<input type="text"
class="form-control search-input rounded-3"
id="searchInput" placeholder="Search by name, email, or position">
</div>
<div class="col-md-3">
<label for="departmentFilter" class="form-label fw-bold">Departments</label>
<select id="departmentFilter" class="form-select filter-select rounded-3">
<option value="">All Departments</option>
<option value="Engineering">Engineering</option>
<option value="Marketing">Marketing</option>
<option value="Sales">Sales</option>
<option value="HR">HR</option>
<option value="Finance">Finance</option>
</select>
</div>
<div class="col-md-3">
<label for="statusFilter" class="form-label fw-bold">Status</label>
<select id="statusFilter" class="form-select filter-select rounded-3">
<option value="">All Status</option>
<option value="Active">Active</option>
<option value="Inactive">Inactive</option>
</select>
</div>
<div class="col-md-1 d-flex align-items-end">
<button id="clearBtn" title="Clear All Filters"
class="btn btn-danger btn-lg w-75 text-white fw-bold"
>X</button>
</div>
</div>
</div>
<!-- table -->
<div class="table-container table-responsive">
<table class="table table-striped table-bordered table-hover" id="dataTable">
<thead>
<tr>
<th>ID</th>
<th>Name</th>
<th>Email</th>
<th>Position</th>
<th>Department</th>
<th>Status</th>
</tr>
</thead>
<tbody id="tableBody">
<!-- data will be inserted here form JS -->
</tbody>
</table>
<div id="noResults" class="no-results text-center py-5" style="display: none;">
<div class="display-4 mb-2">š</div>
<div class="fw-bold">No Results Found</div>
<small>Try adjusting your search or filters</small>
</div>
</div>
</div>
</div>
<script src="https://cdn.jsdelivr.net/npm/bootstrap@5.3.8/dist/js/bootstrap.bundle.min.js" integrity="sha384-FKyoEForCGlyvwx9Hj09JcYn3nv7wiPVlz7YYwJrWVcXK/BmnVDxM+D2scQbITxI" crossorigin="anonymous"></script>
<script src="script.js"></script>
</body>
</html>
In your style.css file, add the CSS code to design your Bootstrap 5 Search Filter Table with a clean, modern, and responsive layout. Style the search box, dropdown filters, record counters, and employee table to create a professional user interface with proper spacing, colors, and mobile responsiveness.
body{
background: linear-gradient(135deg, #7f96fa 0%, #915dc4 100%);
min-height: 100vh;
padding: 40px 0;
}
.card{
box-shadow: 0 10px 30px rgba(0,0,0,0.2);
}
.card-header{
background: linear-gradient(135deg, #2349fa 0%, #764ba2 100%);
}
.search-section{
background: #f8f9fa;
}
.search-input, .filter-select{
border: 2px solid #e0e0e0;
padding: 12px 20px;
transition: all 0.3s;
}
.search-input:focus, .filter-select:focus{
border-color: #667eea;
box-shadow: 0 0 0 0.2rem rgba(102,126,234,0.25);
outline: none;
}
.table thead{
background: linear-gradient(135deg, #667eea, #764ba2 100%);
color: white;
}
.table thead th{
padding: 15px;
text-transform: uppercase;
font-size: 0.85rem;
letter-spacing: 0.5px;
}
.table tbody tr:hover{
background-color: #f8f9fa;
}
.stats{
box-shadow: 0 2px 10px rgba(0,0,0,0.1);
}
.number{
color: #667eea;
}
.label{
color: #6c757d;
font-size: 0.8rem;
}
In your script.js file, add JavaScript code to enable real-time search and dropdown filtering for the employee records table. Implement functionality to filter data by Name, Email, Position, Department, and Status, and dynamically update Total Records, Visible Records, and Hidden Records counters without page reload.
// Sample data
const employees = [
{ id: 1, name: 'John Doe', email: 'john.doe@company.com', position: 'Software Engineer', department: 'Engineering', status: 'Active' },
{ id: 2, name: 'Jane Smith', email: 'jane.smith@company.com', position: 'Marketing Manager', department: 'Marketing', status: 'Active' },
{ id: 3, name: 'Mike Johnson', email: 'mike.johnson@company.com', position: 'Sales Representative', department: 'Sales', status: 'Active' },
{ id: 4, name: 'Sarah Williams', email: 'sarah.williams@company.com', position: 'HR Specialist', department: 'HR', status: 'Inactive' },
{ id: 5, name: 'David Brown', email: 'david.brown@company.com', position: 'Financial Analyst', department: 'Finance', status: 'Active' },
{ id: 6, name: 'Emily Davis', email: 'emily.davis@company.com', position: 'Senior Developer', department: 'Engineering', status: 'Active' },
{ id: 7, name: 'Robert Wilson', email: 'robert.wilson@company.com', position: 'Content Writer', department: 'Marketing', status: 'Active' },
{ id: 8, name: 'Lisa Anderson', email: 'lisa.anderson@company.com', position: 'Sales Manager', department: 'Sales', status: 'Active' },
{ id: 9, name: 'James Taylor', email: 'james.taylor@company.com', position: 'Recruiter', department: 'HR', status: 'Active' },
{ id: 10, name: 'Maria Garcia', email: 'maria.garcia@company.com', position: 'Accountant', department: 'Finance', status: 'Inactive' },
{ id: 11, name: 'Christopher Lee', email: 'chris.lee@company.com', position: 'DevOps Engineer', department: 'Engineering', status: 'Active' },
{ id: 12, name: 'Jessica Martinez', email: 'jessica.martinez@company.com', position: 'SEO Specialist', department: 'Marketing', status: 'Active' },
{ id: 13, name: 'Daniel Rodriguez', email: 'daniel.rodriguez@company.com', position: 'Business Developer', department: 'Sales', status: 'Active' },
{ id: 14, name: 'Amanda Thomas', email: 'amanda.thomas@company.com', position: 'Training Coordinator', department: 'HR', status: 'Active' },
{ id: 15, name: 'Matthew Hernandez', email: 'matthew.hernandez@company.com', position: 'CFO', department: 'Finance', status: 'Active' }
];
const searchInput = document.getElementById('searchInput');
const departmentFilter = document.getElementById('departmentFilter');
const statusFilter= document.getElementById("statusFilter")
const clearBtn = document.getElementById('clearBtn')
const tableBody = document.getElementById('tableBody')
const noResults = document.getElementById('noResults')
const totalRecords= document.getElementById('totalRecords')
const visibleRecords= document.getElementById('visibleRecords')
const hiddenRecords= document.getElementById('hiddenRecords')
// functions to render table
function renderTable(data){
tableBody.innerHTML = "";
if(data.length === 0){
noResults.style.display = 'block';
// update stats calling
updateStats(0);
return
}
noResults.style.display = 'none';
data.forEach((employee) => {
const row = document.createElement('tr');
const statusClass = employee.status === "Active" ? "bg-success" : "bg-secondary";
row.innerHTML = `
<td><strong>#${employee.id}</strong></td>
<td>${employee.name}</td>
<td>${employee.email}</td>
<td>${employee.position}</td>
<td>${employee.department}</td>
<td><span class='badge rounded-5 py-2 px-3 ${statusClass}'>${employee.status}</span></td>
`;
tableBody.appendChild(row);
})
// update stats call
updateStats(data.length)
}
// function to update statistics
function updateStats(visible){
const total = employees.length;
const hidden = total - visible;
totalRecords.textContent = total;
visibleRecords.textContent = visible;
hiddenRecords.textContent = hidden;
}
// function to filter data
function filterData(){
const searchTerm = searchInput.value.toLowerCase().trim();
const departmentValue = departmentFilter.value;
const statusValue = statusFilter.value;
const filterData = employees.filter((employee) => {
// search filter
const matchesSearch =
employee.name.toLocaleLowerCase().includes(searchTerm) ||
employee.email.toLocaleLowerCase().includes(searchTerm) ||
employee.position.toLocaleLowerCase().includes(searchTerm);
// department filter
const matchesDepartment =
departmentValue === "" || employee.department === departmentValue;
// status filter
const matchesStatus = statusValue === "" || employee.status === statusValue;
return matchesSearch && matchesDepartment && matchesStatus;
});
renderTable(filterData)
}
// function to clear all filter
function clearFilters(){
searchInput.value = ""
departmentFilter.value = ""
statusFilter.value = ""
renderTable(employees)
}
// event listener filerdata
searchInput.addEventListener('input',filterData);
departmentFilter.addEventListener('change',filterData)
statusFilter.addEventListener('change',filterData);
clearBtn.addEventListener('click',clearFilters)
// intially calll
renderTable(employees);
