I've just figure out a way to iterate of the rows and cells of a band but it really seems messy. Can someone tell me if there is a better way to do this. In this there is an attempt that I made to do this in what I thought was a simpler way but it does not work. Any comments would be welcomed.
Why when I update a single cell does this event fire multiple times? This is not what I expected. I really expected this to get fired once for the row/cell that was updated.
function afterCellUpdate(gridClientId, cellId) { var grid = igtbl_getGridById(gridClientId); var band = igtbl_getBandById(cellId); var cell = igtbl_getCellById(cellId); var row = igtbl_getRowById(cellId); var gridRows = grid.Rows; var bandKey = band.Key; if (bandKey == 'Invoice') { var discount = row.getCellFromKey('Discount').getValue(); var childRowCount = row.ChildRowsCount; for (var i = 0; i < childRowCount; i++) { var childRow = row.getChildRow(i); childRow.getCellFromKey('Discount').setValue(discount); } } else if (bandKey == 'InvoiceItem') { var rateCell = row.getCellFromKey('Rate'); var rate = rateCell.getValue(); var discountCell = row.getCellFromKey('Discount'); var discount = discountCell.getValue(); var totalCell = row.getCellFromKey('Total'); var total = rate * (1 - discount / 100); totalCell.setValue(total); var invoiceTotal = 0;
// I tried this but it only iterates over a single top level band. // This does not iterate over the child band rows, why not?// for (var i = 0; i < gridRows.length; i++) {// gridRow = gridRows.getRow(i);// var bandKey = gridRow.Band.Key;// if (bandKey == 'InvoiceItem') {// var invoiceTotal = row.getCellFromKey('Total').getValue();// }// } // Iterate over the current Invoice.InvoiceItem collection. var parentRow = row.ParentRow; var parentBandKey = parentRow.Band.Key; var childRowCount = parentRow.ChildRowsCount; for (var i = 0; i < childRowCount; i++) { var childRow = parentRow.getChildRow(i); invoiceTotal += childRow.getCellFromKey('Total').getValue(); } // getFirstRow Returns the first row of the current rows parent collection. // getChildRows var invoiceTotalCell = parentRow.getCellFromKey('Total'); invoiceTotalCell.setValue(invoiceTotal); }}
If I'm doing the following, why does it only iterate over a single band? The InvoiceItem band is never found, this only goes over the Invoice band.
for (var i = 0; i < gridRows.length; i++) { gridRow = gridRows.getRow(i); var bandKey = gridRow.Band.Key; if (bandKey == 'InvoiceItem') { var invoiceTotal = row.getCellFromKey('Total').getValue(); }}
Great -- thanks for sharing, I am sure will be helpful to a lot of people. I have added some tags to the post so that more people come here via search.
It might not be 100% complete now but I think it's good enough to share. If anyone else needs to use client side code to update a monetary total of a row using a base value and a discount here you go.
<script type="text/javascript">function beforeCellUpdate(gridClientId, cellId, newValue) { var grid = igtbl_getGridById(gridClientId); var band = igtbl_getBandById(cellId); var bandKey = band.Key; if (bandKey == 'Invoice') { var invoiceRow = igtbl_getRowById(cellId); var invoiceCell = igtbl_getCellById(cellId); if (invoiceCell.Column.Key == 'Discount') { var invoiceDiscount = newValue; var childRowCount = invoiceRow.ChildRowsCount; // Iterate over Invoice Items and update cell values. for (var i = 0; i < childRowCount; i++) { // Get InvoiceItem row from Invoice row. var invoiceItemRow = invoiceRow.getChildRow(i); // Get current rate value from InvoiceItem.Rate cell. var rate = invoiceItemRow.getCellFromKey('Rate').getValue(); // Set InvioceItem.Discount cell to value entered into Invoice.Discount cell. invoiceItemRow.getCellFromKey('Discount').setValue(invoiceDiscount); // Get calculated InvoiceItem.Total. invoiceItemTotal = getInvoiceItemTotal(rate, invoiceDiscount); // Set InvoiceItem.Total cell value to calculated value. invoiceItemRow.getCellFromKey('Total').setValue(invoiceItemTotal); } // Get calculated Invoice total. var invoiceTotal = getInvoiceTotal(invoiceRow); // Set Invoice.Total cell value to calculated value. invoiceRow.getCellFromKey('Total').setValue(invoiceTotal); } } if (bandKey == 'InvoiceItem') { var invoiceItemRow = igtbl_getRowById(cellId); var invoiceItemCell = igtbl_getCellById(cellId); var rate = invoiceItemRow.getCellFromKey('Rate').getValue(); var discount = invoiceItemRow.getCellFromKey('Discount').getValue(); if (invoiceItemCell.Column.Key == 'Rate') { // If rate changed use newValue for rate. rate = newValue; } else if (invoiceItemCell.Column.Key == 'Discount') { // If discount changed use newValue for discount. discount = newValue; } // Get calculated InvoiceItem.Total. var invoiceItemTotal = getInvoiceItemTotal(rate, discount); invoiceItemRow.getCellFromKey('Total').setValue(invoiceItemTotal); var invoiceRow = invoiceItemRow.ParentRow; var invoiceTotal = getInvoiceTotal(invoiceRow); // Set InvoiceItem.Total cell value to calculated value. invoiceRow.getCellFromKey('Total').setValue(invoiceTotal); }}// Calculates the total from the rate and discount.function getInvoiceItemTotal(rate, discount) { var total = 0; total = rate * (1 - discount / 100); return total;}// Iterates over the InvoiceItem rows to sum the item totals.function getInvoiceTotal(invoiceRow) { var invoiceTotal = 0; var invoiceItemCount = invoiceRow.ChildRowsCount; // Iterate over the current Invoice.InvoiceItem row collection. for (var i = 0; i < invoiceItemCount; i++) { var invoiceItemRow = invoiceRow.getChildRow(i); invoiceTotal += invoiceItemRow.getCellFromKey('Total').getValue(); } return invoiceTotal;}</script>
Hello,
Yes, it is a good question. I went through your sample code and this is indeed the best way to iterate through the rows on the client. There is indeed one tricky part where to get from the parent to child bands you need to call the getChildRows() method for a row, that is for each row in the parent band you may call getChildRows to get to its respective child rows from the child band, if they exist, e.g.
for( j = 0; j < row.getChildRows().length; ++j )
Hope this helps.