-1

I'm pretty new to this, and I'm having trouble getting the output I'm looking for. I have a web page where I'd like to display my CSV in a nice looking table. The output is not being displayed on the web page at all when I access the local port. When I go to inspect and then the network tab, I can see that the GET to /data is working. It returns 200, type JSON, and I see the JSON body. Where is the point that's going wrong? Inspect shows JSON returned and logs show 'sending data in res.json' but no 'fetch' (from script.js). Clearly never got there, but why is that and how can I fix it?

script.js:

// Function to fetch CSV data from the server and render it as a table
const fetchAndRenderCSV = async () => {
    try {
        console.log('trying fetch /data')
        const response = await fetch('/data');
        console.log('Response is: ' + response)
        const csvData = await response.json();
        console.log(csvData)
        renderCSVTable(csvData);
    } catch (error) {
        console.error('Error fetching CSV data:', error);
    }
};

// Function to render CSV data as a table
const renderCSVTable = (data) => {
    const tableContainer = document.getElementById('csvTableContainer');
    const tableHTML = generateTableHTML(data);
    tableContainer.innerHTML = tableHTML;
};

// Function to generate HTML for the table
const generateTableHTML = (data) => {
    let tableHTML = '<table>';
    // Assuming the first row contains headers
    tableHTML += '<tr>';
    for (let i = 0; i < data[0].length; i++) {
        tableHTML += `<th>${data[0][i]}</th>`;
    }
    tableHTML += '</tr>';

    // Add rows for each data entry (excluding the header row)
    for (let i = 1; i < data.length; i++) {
        tableHTML += '<tr>';
        for (let j = 0; j < data[i].length; j++) {
            tableHTML += `<td>${data[i][j]}</td>`;
        }
        tableHTML += '</tr>';
    }

    tableHTML += '</table>';
    return tableHTML;
};

const submitGuess = async () => {
try {
    // Clear result and error messages
    resultMessage.textContent = '';
    errorMessage.textContent = '';

    const inputValue = userInput.value.trim();
    if (inputValue === '') {
        errorMessage.textContent = 'Please enter a name before submitting.';
        return;
    }

    const response = await fetch('/handleInput', {
        method: 'POST',
        headers: {
            'Content-Type': 'application/json',
        },
        body: JSON.stringify({ userInput: inputValue }),
    });

    const data = await response.json();

    if (data.isCorrect) {
        resultMessage.textContent = 'Correct answer!';
        resultMessage.classList.add('correct-answer');
    } else {
        // Shake animation on incorrect guess
        userInput.classList.add('shake');

        // Remove the 'shake' class after the animation ends
        userInput.addEventListener('animationend', () => {
            userInput.classList.remove('shake');
        });

        resultMessage.textContent = 'Incorrect answer.';
        resultMessage.classList.remove('correct-answer'); // Remove the class if present
    }

    userInput.value = '';
} catch (error) {
    console.error('Error:', error);
}
};

// Call the function to fetch and render CSV data when the page loads
console.log('fetch')
fetchAndRenderCSV();

styles.css:

body {
  font-family: Arial, sans-serif;
  text-align: center;
}

#game {
  margin: 20px auto;
  max-width: 400px;
}

#word {
  font-size: 2em;
  margin-bottom: 20px;
}

#guess {
  padding: 5px;
  font-size: 1.2em;
  width: 100px;
  margin-bottom: 10px;
}

#feedback {
  margin-top: 20px;
  font-weight: bold;
}

@keyframes shake {
  0% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-5px);
  }
  50% {
    transform: translateX(5px);
  }
  75% {
    transform: translateX(-5px);
  }
  100% {
    transform: translateX(0);
  }
}

.shake {
  animation: shake 0.4s ease-in-out;
}

index.html

<h1>Guess</h1>

<div id="csvTableContainer"></div>
<!-- This is where the table will be rendered -->

<form id="guessForm">
  <label for="userInput">Enter Guess:</label>
  <input type="text" id="userInput" name="userInput" required>
  <button type="button" onclick="submitGuess()" id="submitButton">Submit</button>
</form>

<button onclick="playAgain()" id="playAgainButton">Play Again</button>

<!-- Result message with inline style for correct answer -->
<p id="resultMessage" style="color: green;"></p>

<!-- Error message -->
<p id="errorMessage" style="color: red;"></p>

My server.js:

const puppeteer = require('puppeteer');
const fs = require('fs');
const Papa = require('papaparse');
// const Parse = require('parse');
const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const { spawn } = require('child_process');

const app = express();
const port = 3000;

app.use(express.static(path.join(__dirname, 'public')));
app.use(bodyParser.json());

let isCorrect = false;
let answer, filePath;

app.get('/data', (req, res) => {
    try {
        // Read CSV file
        const csvData = fs.readFileSync(filePath, 'utf8');

        // Parse CSV data
        const parsedData = Papa.parse(csvData, { header: true }).data;

        // Send parsed CSV data as JSON
        console.log('sending data in res.json')
        const ret = res.json(parsedData);
        // console.log(ret)
    } catch (error) {
        console.error('Error reading or parsing CSV file:', error);
        res.status(500).send('Internal Server Error');
    }
});


app.listen(port, () => {
    console.log(`Server is running at http://localhost:${port}`);
    generateCorrectAnswer();
    console.log('The correct answer is: ', answer)
    console.log('filePath is: ' + filePath)
    checkFileExists(filePath)
    readAndParseCSV(filePath);
});
10
  • 1
    The only function I assume is responsible for creating the table to be displayed is not shown, while it looks like your problem comes from there... Commented Feb 9, 2024 at 14:21
  • fixed that sorry! Commented Feb 9, 2024 at 14:28
  • Do you get a result (and can you provide a sample of it) from these lines: const csvData = await response.json(); console.log(csvData) ? Commented Feb 9, 2024 at 14:48
  • 1
    No I don't get a response. It never even logs the 'trying fetch /data' Commented Feb 9, 2024 at 14:56
  • Where do you make the call fetchAndRenderCSV()? It's not included in your code. See minimal reproducible example. Commented Feb 9, 2024 at 15:04

2 Answers 2

-1

It looks like you weren't actually calling your fetchAndRenderCSV() function. In the below snippet I modified the function a little bit to digest a CSV-type input (instead of the pre-processed JSON) and at the end of the snippet I actually call the rendering function:

// Function to fetch CSV data from the server and render it as a table
const fetchAndRenderCSV = async () => {
    try {
        console.log('trying fetch /data')
        const csvText = await fetch('https://support.staffbase.com/hc/en-us/article_attachments/360009197031').then(r=>r.text());
        let csvData = Papa.parse(csvText,{header:false,skipEmptyLines:true}).data;
        renderCSVTable(csvData);
    } catch (error) {
        console.error('Error fetching CSV data:', error);
    }
};

// Function to render CSV data as a table
const renderCSVTable = (data) => {
    const tableContainer = document.getElementById('csvTableContainer');
    const tableHTML = generateTableHTML(data);
    tableContainer.innerHTML = tableHTML;
};

// Function to generate HTML for the table
const generateTableHTML = (data) => {
    let tableHTML = '<table>';
    // Assuming the first row contains headers
    tableHTML += '<tr>';
    for (let i = 0; i < data[0].length; i++) {
        tableHTML += `<th>${data[0][i]}</th>`;
    }
    tableHTML += '</tr>';

    // Add rows for each data entry (excluding the header row)
    for (let i = 1; i < data.length; i++) {
        tableHTML += '<tr>';
        for (let j = 0; j < data[i].length; j++) {
            tableHTML += `<td>${data[i][j]}</td>`;
        }
        tableHTML += '</tr>';
    }
    tableHTML += '</table>';
    return tableHTML;
};

fetchAndRenderCSV();
body {
  font-family: Arial, sans-serif;
  text-align: center;
}

#game {
  margin: 20px auto;
  max-width: 400px;
}

#word {
  font-size: 2em;
  margin-bottom: 20px;
}

#guess {
  padding: 5px;
  font-size: 1.2em;
  width: 100px;
  margin-bottom: 10px;
}

#feedback {
  margin-top: 20px;
  font-weight: bold;
}

@keyframes shake {
  0% {
    transform: translateX(0);
  }
  25% {
    transform: translateX(-5px);
  }
  50% {
    transform: translateX(5px);
  }
  75% {
    transform: translateX(-5px);
  }
  100% {
    transform: translateX(0);
  }
}

.shake {
  animation: shake 0.4s ease-in-out;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/PapaParse/5.4.1/papaparse.min.js"></script>
<h1>Guess</h1>

<div id="csvTableContainer"></div>
<!-- This is where the table will be rendered -->

<form id="guessForm">
  <label for="userInput">Enter Guess:</label>
  <input type="text" id="userInput" name="userInput" required>
  <button type="button" onclick="submitGuess()" id="submitButton">Submit</button>
</form>

<button onclick="playAgain()" id="playAgainButton">Play Again</button>

<!-- Result message with inline style for correct answer -->
<p id="resultMessage" style="color: green;"></p>

<!-- Error message -->
<p id="errorMessage" style="color: red;"></p>

I also modified the fetch-URL in order to have a workable snippet here in SO.

Sign up to request clarification or add additional context in comments.

4 Comments

I tried this and the result seems to be pretty much the same. The web page doesn't display and CSV/table data. The inspect > network tab shows GET to support.staffbase.com/hc/en-us/article_attachments/360009197031 returned 200. Type was CSV in this case instead of mine where it said JSON. Problem is, it still doesn't show on the web page
Hmm, somewhere on your page you must be doing something different. The above snippet does work. 🤷
Ya I'm not sure. For this example, where is submitGuess() and the /data? I don't think I understand how all the pieces here are connected
The way SO works is that you present a problem in the form of an MVCE. This way way every question (with their answers) serves as a lesson to other people having similar problems. SO is not a place where you can expect a quality check for your complete web page.
-1

You certainly need to include submitGuess() to fire off the whole process.

You should create smaller reduced cases for the best answers.

You may find constructing DOM nodes easier with methods like:

const apiEndpoint = "https://jsonplaceholder.typicode.com/users";
const tableContainer = document.getElementById('csvTableContainer');
const parser = new DOMParser();

const submitGuess = () => {
  fetchAndRenderCSV();
};

const playAgain = () => {
  tableContainer.querySelector("table").remove();
};

const fetchAndRenderCSV = async () => {

    const response = await fetch(apiEndpoint);
    const jsonData = await response.json();
    renderTable(jsonData);

};

const renderTable = (jsonData) => {

    // create the DOM node
    const table = parser.parseFromString(`<table>
      <thead>
        <th>username</th>
        <th>email</th>
        <th>website</th>
      </thead>
      <tbody>
      </tbody>
    </table>`, "text/html");
    
    // a reference to where rows should be inserted
    const insertionPoint = table.body.firstChild.querySelector("tbody");
   
    jsonData.forEach(user => {
       
       // construct row from data
       const row = `<tr>
           <td>${user.username}</td>
           <td>${user.email}</td>
           <td>${user.website}</td>
       </tr>
       `;
      
       // inject row into table
       insertionPoint.insertAdjacentHTML("beforeend", row);       
       
    });
      
    // now inject the entire table into page
    tableContainer.append(table.body.firstChild);

};
table, th, td {
  border: 1px solid;
}

thead {
  background-color: gray;
  color: white;
}
<button type="button" onclick="submitGuess()" id="submitButton">fetch and render</button>
<button type="reset" onclick="playAgain()" id="playAgainButton">reset</button>

<div id="csvTableContainer"></div>

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.