3

The table is like this:

<table id="sample_table">
  <tr>
   <td>1</td>
   <td><input type="text" size="5" id="in2" name="txt2" value="0"/></td>
   <td><input type="text" size="5" id="in3" name="txt3" value="0"/></td>
   <td><input type="text" size="5" id="in4" name="txt4" value="0"/></td>
 </tr>

the js code is like this:

function export(filename) {
    var csv = [];
    var rows = document.getElementById('tbl_posts').querySelectorAll("table tr");

    for (var i = 0; i < rows.length; i++) {

        var row = [], cols = rows[i].querySelectorAll("td, th");
    
        for (var j = 0; j < cols.length; j++){
            row.push(cols[j].innerText);
        }
            
        csv.push(row.join(","));

}

// Download CSV file not posted here
downloadCSV(csv.join("\n"), filename);
}

and the export button:

<button type="button" onclick="export('myFile')">Export</button>

since it reads td not input fields it adds empty '' strings into csv list. How can I access inputs and push them into row list?

5 Answers 5

3

If you can ensure only inputs occur as child nodes inside a td you could use the following approach. When iterating over a td check if there are any child nodes (only happens in your example if an input is inside a td).

If there's a child (input) use .value on the child to get the value. Otherwise use .innerText. If there is something unclear, feel free to comment :)

function fetchData(filename) {
  var csv = [];
  var rows = document.getElementById('sample_table').querySelectorAll("table tr");

  for (var i = 0; i < rows.length; i++) {

    var row = [],
      cols = rows[i].querySelectorAll("td, th");

    for (var j = 0; j < cols.length; j++) {
      if (cols[j].children.length > 0) { //assuming your structure is always the same and the table only contains inputs as child elements inside a td
        row.push(cols[j].firstChild.value);
      } else {
        row.push(cols[j].innerText);
      }
    }

    csv.push(row.join(","));

  }
  console.log(csv);
}
<table id="sample_table">
  <tr>
    <td>1</td>
    <td><input type="text" size="5" id="in2" name="txt2" value="0" /></td>
    <td><input type="text" size="5" id="in3" name="txt3" value="0" /></td>
    <td><input type="text" size="5" id="in4" name="txt4" value="0" /></td>
  </tr>
</table>
<button type="button" onclick="fetchData('myFile')">Export</button>

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

2 Comments

Thanks a lot. Not exactly what I wanted but much smarter solution. I accepted it.
Maybe re-define your problem and I'd gladly try to help you. Start with posting your desired output
2

What I think is you want to push each row's input value into a CSB file. Then you have to change you cols code like this

cols = document.querySelectorAll("td input, the input");
for (var j = 0; j < cols.length; j++){
    row.push(cols[j].value);
}

I think this would work

7 Comments

Thanks for the solution, but it does not work like this, since cols is not input but td.
@Nessi Can you explain this more please?
Cols contain td which inturn contain input. Right?
Sorry I still couldn't get it
I have two types of cells: [td] and [td input]. According to your solution cols[j].value will produce 'undefined' for td cells with no input. I think I can read them separately and join them.
|
2

I saw your comments. If we seek a solution by minimum editing to your code and also I don't know the rest of the document structure, then this will work for multiple rows.

The basic idea is when you already have a table row, then all you need is inputs inside them. So we seek inputs and then go on them one by one.

function exportF(filename) {
var csv = [];
var rows = document.getElementById('sample_table').querySelectorAll("table tr");

for (var i = 0; i < rows.length; i++) {

    var row = [], cols = rows[i].querySelectorAll("input");

    for (var j = 0; j < cols.length; j++){
                    //console.log(cols[j])
        row.push(cols[j].value);
    }
        
    csv.push(row.join(","));

 }
  // Download CSV file not posted here
  console.log(csv.join("\n")); 
}

Link to fiddle: https://jsfiddle.net/tewo2drn/1/

1 Comment

Not what OP asks for. You also skip the normal td element with no input inside. Compare it to my answer and check the difference.
2

You could also go with Array.from and map it

function fetchData() {
   let data = Array.from(document.querySelectorAll("#sample_table td"))
      .map(el => el.firstChild.value || el.innerText)
      .join(",");
  
   console.log(data);
}
<table id="sample_table">
  <tr>
   <td>1</td>
   <td><input type="text" size="5" id="in2" name="txt2" value="0"/></td>
   <td><input type="text" size="5" id="in3" name="txt3" value="0"/></td>
   <td><input type="text" size="5" id="in4" name="txt4" value="0"/></td>
   <button onclick="fetchData()">Fetch</button>
 </tr>

Comments

0

Just a variation on @Aaron's answer, giulp's way :)
... using .map is definitely the way I'd choose, more concise, less error prone, see @Ifaruki's answer for yet another path in this direction

function fetchData(filename) {
  let cells = document.querySelectorAll("table#sample_table tr td");
  // using map over a NodeList -> see below 
  var csv = Array.prototype.map.call(cells, function(cell){
       // if the first is undefined (falsey in js)
       // then return the second, a widely used pattern
       return cell.firstChild.value || cell.innerText;  
  }).join(",");
  console.log(csv);
}
<table id="sample_table">
  <tr>
    <td>1</td>
    <td><input type="text" size="5" id="in2" name="txt2" value="0" /></td>
    <td><input type="text" size="5" id="in3" name="txt3" value="0" /></td>
    <td><input type="text" size="5" id="in4" name="txt4" value="0" /></td>
  </tr>
</table>
<button type="button" onclick="fetchData('myFile')">Export</button>

MDN Array.prototype.map

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.