Solution 1 :

Eureka!

I finally cracked this sun of a gun. Here’s the line that did it:

elementsArray.forEach(element => parsedValue.push(element.value));

I came to this because of this line:
elementsArray.forEach(element => console.log(element.value));

I found that I was able to get the text I would type into the <input> and <select> fields to print to the console, so after a lot of trial-and-error, I wrote that first line to push everything into a new array parsedValue = [], returned parsedValue, and got it to successfully write to the CSV file!

If anyone reading this would like any further clarification on what exactly I’m doing with this project, I’m more than happy to provide it!

Problem :

I’m currently working on an ‘export to csv’ for a client’s questionnaire app where all of the user-input data is captured and written to a .csv file.

There are both <input> and <select> elements that exist in a HTMLcollection captured by a getElementsByTagName(). Below is a snippet of what my HTML looks like:

 <tr>
    <td><input type="text" id="person1" name="person1"></td>
    <td>
        <select name="person1_lang1_primary" id="person1_lang1_select">
            <option value=""></option>
            <option value="english">English</option>
            <option value="Spanish">Spanish</option>
            <option value="other1">Other1 - specify below</option>
            <option value="other2">Other2 - specify below</option>
            <option value="other3">Other3 - specify below</option>
            <option value="other4">Other4 - specify below</option>
        </select>
    </td>
 <tr>

The functions that are working this all out are:

class TableCSVExporter {
constructor (table, includeHeaders = true) {

    this.table = table;
    this.rows = Array.from(table.querySelectorAll("tr"));

    if(!includeHeaders && this.rows[0].querySelectorAll("th").length) {
        this.rows.shift();
    }


}

convertToCSV() {
    const lines = [];
    const numCols = this._findLongestRowLength();

    for(const row of this.rows) {
        let line = "";

        for(let i = 0; i < numCols; i++) {
            if (row.children[i] !== undefined) {
                line += TableCSVExporter.parseCell(row.children[i]);
            }

            line += (i !== (numCols - 1)) ? "," : "";
        }

        lines.push(line);
        // console.log(row);
    }

    return lines.join("n");
}

_findLongestRowLength() {
    return this.rows.reduce((l, row) => row.childElementCount > l ? row.childElementCount : l, 0);
}

static parseCell (tableCell) {

    let input_elements = tableCell.getElementsByTagName("input");
    let select_elements = tableCell.getElementsByTagName("select");

    let inputArray = Array.from(input_elements);
    let selectArray = Array.from(select_elements);

    let elementsArray = [...inputArray, ...selectArray];
    let parsedValue = [...elementsArray];





    // Replace all double quotes with two double quotes
    parsedValue = parsedValue.replace(/"/g, `""`);

    // If value contains comma, new-line or double-quote, enclose in double quotes
    parsedValue = /[", n]/.test(parsedValue) ? `"${parsedValue}"` : parsedValue;



    inputArray.forEach(element => console.log(element.value));
    selectArray.forEach(element => console.log(element.value));

    elementsArray.forEach(element => console.log(element.value));


    return parsedValue;

}

}

There is also a <script> in the HTML file that holds the following:

<script>
    const primaryInputByPerson = document.getElementById("primaryInputByPerson");
    const btnExportCSV = document.getElementById("btnExportToCSV");


    btnExportCSV.addEventListener("click", () => {
        const exporter = new TableCSVExporter(primaryInputByPerson);
        const csvOutput = exporter.convertToCSV();
        const csvBlob = new Blob([csvOutput], {type: "text/csv" });
        const blobURL = URL.createObjectURL(csvBlob);

        const anchorElement = document.createElement("a");

        anchorElement.href = blobURL;
        // sets the name of the file the user will download
        anchorElement.download = "LEAT-data.csv";
        anchorElement.click();

        // reduces the amount of memory used by the browser
        setTimeout(() => {
            URL.revokeObjectURL(blobURL);
        }, 500);
    })

    // console.log(new TableCSVExporter(primaryInputByPerson).convertToCSV());



</script>

I’ve got it to a point where I can console.log each element’s user-inputted value from inputArray and selectArray, though I can’t seem to figure out how to get parsedValue to hold the values. I converted tableCell into an array because I read that NodeLists and HTMLcollections don’t offer the same features as regular arrays. I’m essentially trying to use .value to get the values as you would do in most DOM scenarios.

The .csv file that gets downloaded will either show undefined, null, or [object HTMLInputElement]/[object HTMLSelectElement] depending on what I console.log().

This is my first question here on the site. I imagine I may be breaking some (or a lot) of conventions, and welcome any feedback on asking better questions in the future!

Note: I give all credit to Domenic Corso and his video https://www.youtube.com/watch?v=cpHCv3gbPuk&t=713s for coming up with nearly all of the code above!

Comments

Comment posted by GottZ

well.. the input element has the id

Comment posted by azt3k

Thanks for the feedback @GottZ ! I tried using .getElementById() on tableCell, though it throws an error saying “getElementById is not a function”… And on top of that, I didn’t mention in my question that my app has many and