Back to all How-tos Cloning your way through nested tables This How-To with accompanying sample explains how to programatically generate a detail table including nested items, in the most efficient way possible. The method used here is generally refered to as Cloning, since we create copies of the tables and rows, editing them as we go along. The Data and Requirements The idea of the nested tables is that you have data that has more than 2 levels. A “regular” transactional documents is: Record - Field1 - Field2 - Field3 - DetailTable[0] - Field1 - Field2 - DetailTable[1] - Field1 - Field2 - DetailTable[2] - Field1 - Field2 However, a nested table would be: Record - Field1 - Field2 - Field3 - DetailTable[0] - Field1 - Nested[0] - Subfield1 - Subfield2 - Nested[1] - Subfield1 - Subfield2 - DetailTable[1] - Field1 - Nested[0] - Subfield1 - Subfield2 - DetailTable[2] - Field1 This can be achieved inside the DataMapper easily with XML files, but other data types can definitely generate nested tables. The sort of data we’re talking about are report, multi-service invoices, etc. In the sample provided in this how-to, an Account Status Report is sent to a reseller which contains data for multiple invoices, each with their own services. The Basic Idea So let’s say we have this little tidbit of HTML in our page: <table id="base" class="dynamic"> <tr> <td>Row1</td> <td>Row2</td> </tr> </table> We could use the following script to create 2 copies of the table, with 5 copies of the row in each of these tables. For the purpose of the example, that the script is attached to an element right above the first table (like a paragraph). // Get base table const baseTable = query("#base"); // Create clone const clone = baseTable.clone(); // Change the ID of the clone table (must be unique!) clone.attr("id", "clone"); // Append the copy results.after(clone); // loop on each table by selecting them with a class query(".dynamic").each(function(table) { // select the first row, the TR, which is the first child of the table. const baseRow = table.children()[0]; // loop 5 times, changing the row contents every time for(let i; i<=5; i++) { let rowClone = baseRow.clone(); // Change text (normally with data from the sub-tables in the record!) rowClone.find("Row1").text("Row1-"+i); rowClone.find("Row2").text("Row2-"+i); table.append(rowClone); } // Remove the first row (as we're not filling it up) baseRow.remove(); }); This example has been greatly simplified for the purpose of this how-to and to attempt to simplify the concepts used in the sample template. It’s clearly still a complex scripting even this simple – Dynamic Nested Tables are not for the faint of heart. If you’ve had any experience in web development however, you might feel comfortable here. Now that we’ve seen how the script works, it’s time to take a look at the actual files. You can download the following and run them (please note that Connect 1.5 or higher is required to view them). DynamicNestedTablesUsingClone.OL-datamapper DynamicNestedTablesUsingClone.OL-template In Connect 1.5.0, a minor issue causes margins in Preview to not correctly displayed. Updating to version 1.6.1 or higher resolves this issue, which does not affect output either way. Tags Designer scripts Leave a Reply Cancel reply Your email address will not be published. Required fields are marked *Cancel Notify me of followup comments via e-mail. You can also subscribe without commenting. Δ