Introduction
Recently, I built a CSV Viewer App using only HTML, CSS, and JavaScript. This app allows users to upload a CSV file and view its contents in a neatly formatted table. It was my first step into handling file uploads, parsing data, and rendering dynamic tables without relying on any frameworks or libraries. In this blog, I’ll share the key features of the app, challenges I faced, and what I learned along the way.
Key Features of the CSV Viewer App
File Upload
Users can upload a CSV file using an
<input type="file">
element.The uploaded file is read as plain text using the
FileReader
API.Example:
document.getElementById('file').addEventListener('change', function (event) { const file = event.target.files?.[0]; if (file) { const reader = new FileReader(); reader.onload = function (e) { const csvText = e.target.result; renderTable(parseCSV(csvText)); }; reader.readAsText(file); } });
CSV Parsing
The CSV file is parsed into structured data by splitting rows (
\n
) and columns (,
).Quoted values and extra spaces are handled using regex and trimming.
Example:
function parseCSV(csvText) { if (!csvText) return { headers: [], data: [] }; const [headerRow, ...rows] = csvText.split('\n').map(row => row.trim()).filter(Boolean); const headers = headerRow.split(',').map(header => header.replace(/^"|"$/g, '').trim()); const data = rows.map(row => row.split(',').map(column => column.replace(/^"|"$/g, '').trim())); return { headers, data }; }
Dynamic Table Rendering
The parsed data is dynamically rendered into an HTML table using JavaScript.
Example:
function renderTable({ headers, data }) { const tableElement = document.getElementById('table'); if (!tableElement) return; tableElement.innerHTML = ''; // Clear existing content tableElement.appendChild(createRow(headers, 'th')); // Add header row data.forEach(row => tableElement.appendChild(createRow(row, 'td'))); // Add data rows } function createRow(columns, cellTag) { const rowElement = document.createElement('tr'); columns.forEach(text => { const cell = document.createElement(cellTag); cell.textContent = text; rowElement.appendChild(cell); }); return rowElement; }
Styling with CSS
Basic CSS styling enhances the user experience with alternating row colors and hover effects.
Example:
table { border-collapse: collapse; width: 100%; } th, td { border: 1px solid #ddd; padding: 8px; text-align: left; } tr:nth-child(even) { background-color: #f9f9f9; } tr:hover { background-color: #f1f1f1; } th { background-color: #4CAF50; color: white; }
Challenges and Solutions
Challenge: Large Files
Problem: Rendering large datasets caused performance issues.
Solution: Used pagination logic to limit the number of rows displayed at once.
Challenge: Edge Cases
Problem: Quoted values and extra spaces caused parsing errors.
Solution: Used regex and trimming to clean the data before rendering.
Challenge: Reusability
Problem: Hardcoding table logic made it difficult to reuse.
Solution: Modularized functions like
parseCSV
,renderTable
, andcreateRow
for better maintainability.
Lessons Learned
File Handling
- Learned how to use the
FileReader
API to read files asynchronously.
- Learned how to use the
Data Parsing
- Gained hands-on experience parsing CSV data into structured JSON objects.
Dynamic DOM Manipulation
- Built dynamic tables by creating and appending elements programmatically.
User Experience
- Enhanced the UI with basic CSS styling for better readability.