Building a CSV Viewer App with Pure HTML, CSS, and JavaScript

Building a CSV Viewer App with Pure HTML, CSS, and JavaScript

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

  1. 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);
          }
        });
      
  2. 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 };
        }
      
  3. 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;
        }
      
  4. 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

  1. Challenge: Large Files

    • Problem: Rendering large datasets caused performance issues.

    • Solution: Used pagination logic to limit the number of rows displayed at once.

  2. Challenge: Edge Cases

    • Problem: Quoted values and extra spaces caused parsing errors.

    • Solution: Used regex and trimming to clean the data before rendering.

  3. Challenge: Reusability

    • Problem: Hardcoding table logic made it difficult to reuse.

    • Solution: Modularized functions like parseCSV, renderTable, and createRow for better maintainability.


Lessons Learned

  1. File Handling

    • Learned how to use the FileReader API to read files asynchronously.
  2. Data Parsing

    • Gained hands-on experience parsing CSV data into structured JSON objects.
  3. Dynamic DOM Manipulation

    • Built dynamic tables by creating and appending elements programmatically.
  4. User Experience

    • Enhanced the UI with basic CSS styling for better readability.