Dynamic Tables

Contact Us or call 1-877-932-8228
Dynamic Tables

Dynamic Tables

We have seen how to get XML data from the server and display it in the browser. Let's now see how we can use data returned in this way to populate an HTML table.

From the command line/terminal, navigate to the directory PassingData/Demos/ and type npm start, then open http://localhost:8080/Table.html in your browser. When it first loads, the page has a simple button that reads "Show Table." When the button is clicked, the table shows up on the page: Table on Page

The page works as follows:

  1. When the user clicks on the button, JavaScript is used to make a call to Employees, served from the Employees response route in server.js.
  2. The Employees response route in Node.js makes a call to the database, which returns a recordset of all employees in the Employees table. That recordset is looped through to create and return an XML document to the browser. The structure of the XML document is shown below:XML Document Structure(The nodes for Employees 3 through 9 are collapsed in the diagram above.)
  3. As soon as the browser receives and completely loads the response, it iterates through the Employee nodes creating an HTML table and then displays that table on the page.

Let's take a look at the code.

Code Sample:

PassingData/Demos/Table.html
<!DOCTYPE HTML>
<html>
<head>
<meta charset="UTF-8">
<title>Dynamic Table</title>
<link rel="stylesheet" type="text/css" href="Table.css">
<script type="text/javascript" src="lib.js"></script>
<script type="text/javascript">
	function buildTable() {
		removeAllChildren(document.getElementById("HeaderRow"));
		removeAllChildren(document.getElementById("BodyRows"));
		createHeaderRow();
		getRows();
	}

	function createHeaderRow() {
		var headerRow = document.getElementById("HeaderRow");
		var colNames = ["Salesperson", "Title", "Birth Date", "Hire Date", "Extension"];
		var colWidths = [24, 24, 21, 21, 8];

		for (var i = 0; i < colNames.length; i++) {
			var width = colWidths[i];
			var atts = new Object();
			atts["style"] = "width:" + width + "%;";
			addChild(document, headerRow, "th", colNames[i], atts);
		}
	}

	function getRows() {
		var xmlhttp = new XMLHttpRequest();
		xmlhttp.open("get", "Employees", true);
		xmlhttp.onreadystatechange = function() {
			if (this.readyState == 4 && this.status == 200) {
				showResult(this);
			}
		};
		xmlhttp.send(null);
	}

	function showResult(xmlhttp) {
		var xmlDoc = xmlhttp.responseXML.documentElement;
		var tableName = "employees";
		var rowElement = "Employee";
		var outputResult, rowData;

		removeWhitespace(xmlDoc, true);

		outputResult = document.getElementById("BodyRows");
		rowData = xmlDoc.getElementsByTagName(rowElement);
		addTableRowsFromXmlDoc(rowData, outputResult);
	}

	function addTableRowsFromXmlDoc(xmlNodes, tableNode) {
		var theTable = tableNode.parentNode;
		var newRow, newCell, i, j;

		for (i = 0; i < xmlNodes.length; i++) {
			newRow = tableNode.insertRow(i);

			newRow.className = (i % 2) ? "OddRow" : "EvenRow";

			for (j = 0; j < xmlNodes[i].childNodes.length; j++) {
				newCell = newRow.insertCell(newRow.cells.length);
				newCell.innerHTML = decodeURIComponent(xmlNodes[i].childNodes[j].firstChild.nodeValue);
			}
		}
		theTable.appendChild(tableNode);
	}

	observeEvent(window, "load", function() {
		var btnEmployees = document.getElementById("btnEmployees");
		observeEvent(btnEmployees, "click", buildTable);
	});
</script>
</head>
<body>
<button id="btnEmployees">Show Table</button>
<table cellpadding="2" cellspacing="0" id="MainTable">
	<thead>
		<tr id="HeaderRow"></tr>
	</thead>
	<tbody id="BodyRows"></tbody>
</table>
</body>
</html>

Let's walk through the code step by step in the order the page is processed.

  1. The initial HTML in the body of the page looks like this:
    <button id="btnEmployees">Show Table</button> <table cellpadding="2" cellspacing="0" id="MainTable"> <thead> <tr id="HeaderRow"></tr> </thead> <tbody id="BodyRows"></tbody> </table>
    We'll use JavaScript/Ajax to populate the table header row (HeaderRow) and table body rows (BodyRows).
  2. When the page loads, we attach the buildTable() function to the click event of the btnEmployees button:
    observeEvent(window,"load",function() { var btnEmployees = document.getElementById("btnEmployees"); observeEvent(btnEmployees,"click", buildTable); });
  3. The buildTable() function is shown below:
    function buildTable() { removeAllChildren(document.getElementById("HeaderRow")); removeAllChildren(document.getElementById("BodyRows")); createHeaderRow(); getRows(); }
    This function uses the removeAllChildren() function from our lib.js library to empty out the table header row and all the table body rows. It then calls createHeaderRow() and getRows(). We'll examine those next.
  4. createHeaderRow() looks like this:
    function createHeaderRow() { var headerRow = document.getElementById("HeaderRow"); var colNames = ["Salesperson","Title","Birth Date", "Hire Date","Extension"]; var colWidths = [24,24,21,21,8]; for (var i=0; i<colNames.length; i++) { var width=colWidths[i]; var atts = new Object(); atts["style"] = "width:" + width + "%;"; addChild(document, headerRow, "th", colNames[i], atts); } }
    This function creates arrays to hold the column names (colNames) and widths (colWidths) and then loops through the colNames array using the addChild() function from our lib.js library to insert th elements in our table header row.
  5. getRows() takes care of the XMLHttpRequest:
    function getRows() { var xmlhttp = new XMLHttpRequest(); xmlhttp.open("get", "Employees", true); xmlhttp.onreadystatechange = function() { if (this.readyState == 4 && this.status == 200) { showResult(this); } }; xmlhttp.send(null); }
  6. The showResult() function is shown below:
    function showResult(xmlhttp) { var xmlDoc = xmlhttp.responseXML.documentElement; var tableName = "employees"; var rowElement = "Employee"; var outputResult, rowData; removeWhitespace(xmlDoc,true); outputResult = document.getElementById("BodyRows"); rowData = xmlDoc.getElementsByTagName(rowElement); addTableRowsFromXmlDoc(rowData,outputResult); }
    The first line of the function stores the document element of the DOM Document in the xmlDoc variable. After declaring some other variables, we remove all whitespace-only text nodes using the removeWhitespace() function from our lib.js library. The next three lines store the table body in the outputResult variable and the XML nodeList in the rowData variable and pass both to the addTableRowsFromXmlDoc() function.
  7. The addTableRowsFromXmlDoc() function is shown below:
    function addTableRowsFromXmlDoc(xmlNodes,tableNode) { var theTable = tableNode.parentNode; var newRow, newCell, i; for (i=0; i<xmlNodes.length; i++) { newRow = tableNode.insertRow(i); newRow.className = (i%2) ? "OddRow" : "EvenRow"; for (j=0; j<xmlNodes[i].childNodes.length; j++) { newCell = newRow.insertCell(newRow.cells.length); newCell.innerHTML = xmlNodes[i].childNodes[j].firstChild.nodeValue; } } theTable.appendChild(tableNode); }
    This function loops through the passed-in XML nodeList, adding a new table row for each node in the list. It then sets the class name of the row. The inner loop iterates through all the child nodes (e.g, Salesperson, Title, etc.) of the current node (e.g, the current Employee), creating a table data cell for each.
Next