I have created a dynamically created table that contain values. I would like the ‘Total’ row have the sum of the columns when the page is loaded. Currently the ‘Total’ row cells are summed up when value is changed in a cell and you click away. Any help would be much appreciated. Below is my codepen:
Any help will be much appreciated. I have been struggling with this for weeks.
When the user initially opens the page, the table is empty.
Your script then makes a second request to the server for data to fill the table with. This is NOT the same thing as ‘when the user initially opens the page’. This is the definition of asynchronous loading.
Your script, when it receives the data, populates the table.
At THAT point, your script should trigger a notification that the table has changed, and to do a calculation of the totals. When the script is done loading the data.
So, I should probably add the trigger() in the .then of the Ajax request? Also, I think I’m confused as to what my event should be that needs to be an argument of trigger().
Here’s my code that does nothing:
function getData(listName) {
var root = ../dashboard/posts';
$.ajax({
url: root,
method: 'GET'
}).then(function(data) {
if (listName == 'Advisor Staffing') {
buildTable(data, "#AdvStaffing", listName);
$('#AdvStaffing').change(function(){
$('#AdvStaffing').trigger('change');
});
}
});
}
The sum needs to be calculated after the data has been added to the html page. Right now the sum or calculate() function is being called right when the page loads which is incorrect. A simple solution would be to call calculate after buildTable() and replace calculate() in the onload with getData() call instead. You can calculate after buildTable() since buildTable is a synchronous function.
It won’t work because the calculation are triggered due to an change event. I’m not sure how to use load to trigger the calculation. That’s where I’m stuck.
I don’t quite understand why you are complicating the problem when the totals can be calculated immediately after building the table. The code isn’t very flexible or reusable anyway so why complicate it with triggering events when simply calculating totals after building the table will work. Its not like a reusable table/data grid component is being built where it would make sense to add outputs to allow the outside world to interact with actions.
@motor_man, I’m honestly not sure how to calculate after building the table because once in the calculate function, an eventlistener is listening for a ‘change’ in one of the cells. That’s how the calculation is done.
calculate(AdvStaffing, "AdvStaffing");
function calculate(tbl, tblID) {
tbl.addEventListener("change", function(e) { //<------- if I replace with 'load', it doesn't work
if (e.target.tagName === "INPUT") {
var rowNode = e.target.parentNode.parentNode;
//console.log(e);
//console.log(e.target.getAttribute('data-id'));
var colID = e.target.getAttribute('data-id');
var colName = e.target.getAttribute('data-columnName');
var newColValue = e.target.value;
var rowInputs = rowNode.getElementsByTagName('input');
if (tblID == "AdvStaffing") {
var tableNode = e.target.parentNode.parentNode.parentNode;
var columnInputs = tableNode.getElementsByClassName('column1');
var columnInputs2 = tableNode.getElementsByClassName('column2');
var columnInputs3 = tableNode.getElementsByClassName('column3');
var colSum = getColSum(columnInputs);
var colSum2 = getColSum(columnInputs2);
var colSum3 = getColSum(columnInputs3);
tableNode.rows[8].cells[1].innerHTML = colSum;
tableNode.rows[8].cells[2].innerHTML = colSum2;
tableNode.rows[8].cells[3].innerHTML = colSum3;
}
}
})
}
I passed the code through JSLint to help remove a majority of distracting issues, before using the CodePen tidy.
The jQuery loader adds the change event, because it doesn’t make good sense for the calculate function to both add the event listener, and do the calculation.
The e.target variable could be the table object, or an input field, so getting the closest table element helps to make things more flexible.
I was going to move on to preventing the input being added to the bottom total line, but but stopped short before doing that as I seem to be moving beyond the scope of the desired thing to be fixed.