How to add dynamic rows into table rows?

Hello,

I am working on a form in whcih i have to dynamically add fields on the form. I got that working using javascript but now when I am trying to tidy up the form a bit then I am in trouble as I want to use table to put the fields in and when user adds another row then it should come in between that table. How to do it ?

Here’s my code:

<html>
<head>
<title>Test</title>

<script type="text/javascript">
var counter = 0;

window.onload = function () 
{
	document.getElementById('moreFields').onclick = moreFields;
}

function moreFields() 
{
	counter++;
	var newFields = document.getElementById('readroot').cloneNode(true);
	newFields.id = '';
	newFields.style.display = 'block';
	var newField = newFields.childNodes;
	for (var i=0;i<newField.length;i++) {
		var theName = newField[i].name
		if (theName)
			newField[i].name = theName + counter;
	}
	var insertHere = document.getElementById('writeroot');
	insertHere.parentNode.insertBefore(newFields,insertHere);
}

</script>
</head>

<body>
<table width="965" border="1" cellpadding="5" cellspacing="0" align="center" style="border-collapse: collapse">
<tr style="background-color:#000; color:#fff;">
	<td width="35">#</td>
	<td width="321">What</td>
	<td width="95">Icon</td>
	<td width="202">How</td>
	<td width="202">Why</td>
	<td>Act.</td>
</tr>
</table>
<table border="0" cellpadding="0" cellspacing="0" align="center">
<tr>
	<td>
	<form style="margin:0px;" name="frmForm" id="frmForm" method="post" action="formtest.php">	
		<input name="num[]" value="" size="3" />
		<input name="what[]" value="" size="50" />
		<select name="icon[]">
			<option>Knack</option>
			<option>Quality</option>
			<option>Safety</option>
			<option>Enviornment</option>
			<option>Critical</option>
		</select>
		<input name="how[]" value="" size="30" />
		<input name="why[]" value="" size="30" />
		<input type="button" style="width:50px;" id="moreFields" onclick="moreFields();" value="ADD" />
		
		<span id="writeroot"></span>
		<p align="center"><input type="button" onclick="frmForm.submit();" value="Submit" /></p>
	</form>
	</td>
</tr>
</table>

<div id="readroot" style="display:none;">
	<input name="num[]" value="" size="3" />
	<input name="what[]" value="" size="50" />
	<select name="icon[]">
		<option>Knack</option>
		<option>Quality</option>
		<option>Safety</option>
		<option>Enviornment</option>
		<option>Critical</option>
	</select>
	<input name="how[]" value="" size="30" />
	<input name="why[]" value="" size="30" />
	<input type="button" style="width:50px;" value="DEL" onclick="this.parentNode.parentNode.removeChild(this.parentNode);" />
</tr>
</div>

</body>
</html>

Please help.

Thanks.

The red bit doesn’t make sense to me.

Your code seems to work fine. Whenever I click the Add button, a new row is added to the table.

So where do you want the new rows to be inserted?

I’m just stuck asking why you’re closing a TR that isn’t open, why it’s multiple tables, why it’s even tables since you aren’t even using columns on the second one, why those are TD at the top and not TH if those are column headings… etc,etc, etc… The markup is gibberish… the hidden div you’re reading is also bad coding practice, since you should really be building those in the javascript given how badly it falls apart scripting off or worse, CSS off.

Good rule of thumb, if you only have one TD, you don’t need a table… though looking at your form I could see that being a table, you’re just building it all wrong.

Got to strip a turkey clean and get it in the fridge, but if I have time later I’ll take a closer look and show you how I’d approach that.

perhaps the op is self teaching and just wants to test some javascript functionality in which case the standard of the markup is not critical.

I often test javascript functions without giving a damn if the markup is gibberish because it makes no difference to the javascript.

Ok, here’s some cleaned up markup:


<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html
	xmlns="http://www.w3.org/1999/xhtml"
	lang="en"
	xml:lang="en"
><head>

<meta
	http-equiv="Content-Type"
	content="text/html; charset=utf-8"
/>

<meta
	http-equiv="Content-Language"
	content="en"
/>

<link
	type="text/css"
	rel="stylesheet"
	href="screen.css"
	media="screen,projection,tv"
/>

<title>
	Test
</title>

</head><body>

<form id="fromForm" method="post" action="formtest.php">
	<table>
		<thead>
			<tr>
				<th class="count">#</th>
				<th class="what">What</th>
				<th class="icon">Icon</th>
				<th class="how">How</th>
				<th class="why">Why</th>
			</tr>
		</thead><tbody id="formTBODY">
			<tr>
				<td>
					<input type="text" name="num[0]" value="" size="3" />
				</td><td>
					<input type="text" name="what[0]" value="" size="50" />
				</td><td>
					<select name="icon[0]">
						<option>Knack</option>
						<option>Quality</option>
						<option>Safety</option>
						<option>Enviornment</option>
						<option>Critical</option>
					</select>
				</td><td>
					<input type="text" name="how[]" value="" size="30" />
				</td><td>
					<input type="text" name="why[]" value="" size="30" />
				</td>
			</tr>
		</tbody>
	</table>
	<div id="submitsAndControls">
		<input type="submit" onclick="frmForm.submit();" value="Submit" />
		<noscript>
			<p>You must have javascript enabled to add more rows</p>
		</noscript>
	</div>
</form>

<script type="text/javascript" src="clicker.js"></script>

</body></html>

Getting the CSS out of it and into a separate file where it belongs:


#fromForm {
	width:952px;
	margin:0 auto;
}

#fromForm table {
	border-collapse:collapse;
	width:100%;
}

#fromForm th {
	background:#000;
	color:#FFF;
}

#fromForm th,
#fromForm td {
	padding:5px;
	text-align:center;
	border:1px solid #000;
}

#fromform .count {
	width:35px;
}

#fromForm .icon {
	width:95px;
}

#fromForm .how,
#fromForm .why {
	width:202px;
}

#submitsAndControls {
	overflow:hidden; /* wrap floats */
	width:100%; /* trip haslayout, wrap floats IE */
	padding:5px 0;
}

#submitsAndControls input {
	float:left;
}

#submitsAndControls div {
	padding:0.2em 0.4em;
	float:right;
	color:#000;
	background:#DDD;
	border:1px solid #000;
}

As well as getting the script out of there…


(function(){
	var clicker=document.createElement('div');
	clicker.appendChild(document.createTextNode('Click for another row'));
	clicker.counter=0;
	clicker.fieldList=[
		['text','num',3],
		['text','what',50],
		['select','icon',[
			'Knack',
			'Quality',
			'Safety',
			'Environment',
			'Critical'
		]],
		['text','how',30],
		['text','why',30]
	];

	clicker.onclick=function() {
		with (this) {
			counter++;
			var newTR=document.createElement('tr');
			for (var t in fieldList) {
				switch (fieldList[t][0]) {
					case 'text':
						var newInput=document.createElement('input');
						newInput.type='text';
						newInput.size=fieldList[t][2];
					break;
					case 'select':
						var newInput=document.createElement('select');
						for (var n in fieldList[t][2]) {
							var newOption=document.createElement('option');
							newOption.appendChild(document.createTextNode(fieldList[t][2][n]));
							newInput.appendChild(newOption);
						}
					break;
				}
				newInput.name=fieldList[t][1]+'['+this.counter+']';
				var newTD=document.createElement('td');
				newTD.appendChild(newInput);
				newTR.appendChild(newTD);
			}
			document.getElementById('formTBODY').appendChild(newTR);
		}
	}

	document.getElementById('submitsAndControls').appendChild(clicker);
}());

Big changes to the script. Uses an array of values instead of putting something in the DOM that’s gibberish if scripting fails… wraps the whole thing in an anonymous function so you don’t have any globals in the namespace, puts the counter value on the actual click DIV again to keep out of the global space, builds all the elements with the DOM including the ‘click for more’ link, so that scripting off you don’t have a non-functional button.

I also like to run my scripts when included at the end of BODY long before onload is fired, so the elements and any classes/id’s are applied and present before CSS or other things like images are loaded.

Hope this helps.

Oh, and yes, this could be done in half the javascript using innerHTML – it would also use more memory and run slower… trade-offs.