Skip to content
Advertisement

Total sum of a filtered table using vanilla JS

The only consideration for this question is, at the moment, I’m not using jQuery. Here’s the code:

//I think here is where the problem relies, in the function I'm using to calculate the sum of the values under 'Valor' column:
var t1 = document.getElementById("emp-table");
getSum();
function getSum() {
  var sumVal = 0;
  for(var i = 1; i < t1.rows.length; i++){
    sumVal = sumVal + parseInt(t1.rows[i].cells[6].innerHTML);
    document.getElementById("sumV").innerHTML = "Sum Value = "+sumVal;
  }
};

function getUniqueValuesFromColumn() {
    var unique_col_values_dict = {}
    allFilters = document.querySelectorAll(".table-filter")
    allFilters.forEach((filter_i) => {
        col_index = filter_i.parentElement.getAttribute("col-index");
        const rows = document.querySelectorAll("#emp-table > tbody > tr")
        rows.forEach((row) => {
            cell_value = row.querySelector("td:nth-child("+col_index+")").innerHTML;
            if (col_index in unique_col_values_dict) {
                if (unique_col_values_dict[col_index].includes(cell_value)) {
                    //console.log("already exists");
                } else {
                    unique_col_values_dict[col_index].push(cell_value)
                }
            } else {
                unique_col_values_dict[col_index] = new Array(cell_value)
            }
        }); 
    });
    updateSelectOptions(unique_col_values_dict)
};

function updateSelectOptions(unique_col_values_dict) {
    allFilters = document.querySelectorAll(".table-filter")
    allFilters.forEach((filter_i) => {
        col_index = filter_i.parentElement.getAttribute('col-index')
        unique_col_values_dict[col_index].forEach((i) => {
            filter_i.innerHTML = filter_i.innerHTML + `n<option value="${i}">${i}</option>`
        });

    });
};

function filter_rows() {
    allFilters = document.querySelectorAll(".table-filter")
    var filter_value_dict = {}
    allFilters.forEach((filter_i) => {
        col_index = filter_i.parentElement.getAttribute('col-index')
        value = filter_i.value
        if (value != "all") {
            filter_value_dict[col_index] = value;
        }
    });
    var col_cell_value_dict = {};
    const rows = document.querySelectorAll("#emp-table tbody tr");
    rows.forEach((row) => {
        var display_row = true;
        allFilters.forEach((filter_i) => {
            col_index = filter_i.parentElement.getAttribute('col-index')
            col_cell_value_dict[col_index] = row.querySelector("td:nth-child(" + col_index+ ")").innerHTML
        })
        for (var col_i in filter_value_dict) {
            filter_value = filter_value_dict[col_i]
            row_cell_value = col_cell_value_dict[col_i]
            if (row_cell_value.indexOf(filter_value) == -1 && filter_value != "all") {
                display_row = false;
                break;
            }
        }
        if (display_row == true) {
            row.style.display = "table-row"
        } else {
            row.style.display = "none"
        }
    })
};

//And finally, the 'onload' part to update the content:
window.onload = () => {
    console.log(document.querySelector("#emp-table > tbody > tr:nth-child(1) > td:nth-child(2) ").innerHTML);
};
getUniqueValuesFromColumn()
<body>
    <div class="container">
        <div class="card">
            <div class="card-header">
                Lista Pagos
            </div>
            <div class="card-body">
                <table id="emp-table" class="table">
                    <thead>
                        <tr>
                            <th>id</th>
                            <th col-index = 2>Persona
                            <select class="table-filter" onchange="filter_rows()">
                                <option value="all"></option>
                            </select>
                            </th>
                            <th col-index = 3>Servicio
                            <select class="table-filter" onchange="filter_rows()">
                                <option value="all"></option>
                            </select>
                            </th>
                            <th col-index = 4>Año
                            <select class="table-filter" onchange="filter_rows()">
                                <option value="all"></option>
                            </select>
                            </th>
                            <th col-index = 5>Mes
                            <select class="table-filter" onchange="filter_rows()">
                                <option value="all"></option>
                            </select>
                            </th>
                            <th>id Recibo</th>
                            <th>Valor</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr>
                            <td> 33 </td>
                            <td> David Camacho </td>
                            <td> Gas </td>
                            <td> 2022 </td>
                            <td> 4 </td>
                            <td> 7 </td>
                            <td> 10000 </td>
                        </tr>
                    
                        <tr>
                            <td> 32 </td>
                            <td> Héctor Camacho </td>
                            <td> Gas </td>
                            <td> 2022 </td>
                            <td> 4 </td>
                            <td> 7 </td>
                            <td> 15075 </td>
                        </tr>
                    
                        <tr>
                            <td> 30 </td>
                            <td> Héctor Camacho </td>
                            <td> Seguro exequial </td>
                            <td> 2022 </td>
                            <td> 4 </td>
                            <td> 6 </td>
                            <td> 11100 </td>
                        </tr>
                    
                        <tr>
                            <td> 29 </td>
                            <td> María Camacho </td>
                            <td> Seguro exequial </td>
                            <td> 2022 </td>
                            <td> 4 </td>
                            <td> 6 </td>
                            <td> 11100 </td>
                        </tr>
                    
                        <tr>
                            <td> 28 </td>
                            <td> Mateo León </td>
                            <td> Internet </td>
                            <td> 2022 </td>
                            <td> 4 </td>
                            <td> 1 </td>
                            <td> 20000 </td>
                        </tr>
                    
                        <tr>
                            <td> 27 </td>
                            <td> David Camacho </td>
                            <td> Internet </td>
                            <td> 2022 </td>
                            <td> 4 </td>
                            <td> 1 </td>
                            <td> 11600 </td>
                        </tr>
                    
                        <tr>
                            <td> 24 </td>
                            <td> Alba Camacho </td>
                            <td> Internet </td>
                            <td> 2022 </td>
                            <td> 4 </td>
                            <td> 1 </td>
                            <td> 11600 </td>
                        </tr>
                    
                        <tr>
                            <td> 23 </td>
                            <td> María Camacho </td>
                            <td> Internet </td>
                            <td> 2022 </td>
                            <td> 4 </td>
                            <td> 1 </td>
                            <td> 11600 </td>
                        </tr>
                    </tbody>
                </table>
            </div>
        </div>

        <p id="sumV"></p>
        <br/>
        <br/>
    </div>
</body>

So, at the moment, whenever I load the page, the <span> tag already has the total amount if we consider all rows. But, whenever I filter the table, the value there doesn’t change. At first, I tried to do it with a button using onclick, but every time I clicked it, it changed from the total value to ‘undefined’. That’s why I removed that button, and I’m considering to update the content in the <span> tag with the onload segment of my code, but I’ve been unable to achieve it so far.

Any help is greatly appreciated, cheers!

Advertisement

Answer

You could replace your getSum function with the following

function getSum() {
  const rows = [...document.querySelectorAll('#emp-table tr').values()];
  const visibleRows = rows.filter(row => {
    return row.style.display !== 'none';
  });

  let sumVal = 0;
  for (let visibleRow of visibleRows){
    sumVal += parseInt(visibleRow.cells[6].innerHTML);
  }
  document.getElementById("sumV").innerHTML = "Sum Value = " + sumVal;
};

Basically you first filter the rows based on their display value to get just the visibleRows and then sum up the values.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement