Hi,

I have a table in a form like this

<form>
<table>
<tbody id='target'>
<tr id="dolly"><td><input name="hobby[0]" /></td></tr>
</tbody>
</table>
</form>

I also have a button to add a new row, by cloning the 'dolly' tr and appending to 'target'

<input type="button" onclick="AddRow('dolly', 'target') />

May I ask what is the javascript or DOM code to reach the <input> element so that I can change its name attribute? Something like this:

newRow.td.input.name = "hobby[1]";

This may help u:

var inputs = document.getElementsByTagName("input");
var i;
for(i=0; i < inputs.length; i++)
      inputs[i].name="my_name";

Thanks that was very helpful!

But just to confirm, must I always start with document.xxxx? can't I use other objects like newRow?

there are many DOM function to add/del new rows of to create objects. Better google!!

Hi LuckyChap,

I tried googling. and I think I still have problem.

The problem occurs in IE7.

After changing the name using

clonedfield = document.getElementsByName('hobby[0]')[1];
clonedfield.name = 'hobby[1]';

I cannot reference it in another block of code with

// error: clonedfield undefined in IE7. Works in FF2.
clonedfield = document.getElementsByName('hobby[1]')[0];

Why is this so?

ADD:

As a matter of fact, IE7 is behaving really strangely

// if index == 1, nothing returns from getElementsByName
// if index == 0, everything is returned. zzz

alert('getting ' + 'hobby['+ index +']');
inputs = document.getElementsByName('hobby['+ index +']');
for(var i = 0; i < inputs.length; i++)
{
    alert(inputs[i].name);
}

> is not standard function avoid to use this.

On the contrary, it is.

But the implementation between IE and FF doesn't seem like standard.. =( something so simple they have to make it so complicated. I have been tweaking my code so many times just to accomodate both browsers....

[ I further discovered something even more devastating, which I think I should document here in case someoe else needs it. ]

Following the above issue that IE7 cannot reference re-named form fields, BUT able to form.submit the renamed fields, I decided to do only change the names just before submit so I did this:

//////////////////////////////////////
// In IE7,
// expecting an array of five <select>
var hobbies = document.getElementsByName('hobby');
for(var i = 0; i < hobbies.length; i++)
{
     // hobbies.length == 5
     hobbies[i].name = 'hobby[' + i + ']';
     // hobbies.length == 5
}

//////////////////////////////////////
// In FF2
// apparently a reference to the function result is returned
var hobbies = document.getElementsByName('hobby');
for(var i = 0; i < hobbies.length; i++)
{
     // hobbies.length == 5
     hobbies[i].name = 'hobby[' + i + ']';
     // hobbies.length == 4
}

//////////////////////////////////////
// As such, In FF, I have to do
var hobbies = document.getElementsByName('hobby');
num_hobbies = product_ids.length;
or(var i = 0; i < num_hobbies ; i++)
{
      hobbies[0].name = 'hobby[' + i + ']';
      
      // re-retrieve objects
     var hobbies = document.getElementsByName('hobby');
}
// However, this code does not work in IE7!
// IE7 doesn't know about the changed names
// and subsequent getElementsByName() will not work properly!

ARGHHHH... I'm stucked!

I need to change the names to

hobby[0], hobby[1], hobby[2], hobby[3] ...

so that I can pass POST the values to a PHP script...

I need to change the names to

hobby[0], hobby[1], hobby[2], hobby[3] ...

so that I can pass POST the values to a PHP script...

Maybe something along the lines of the following snippet. Rigorous error checking omitted for brevity.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Script-Content-Type" content="text/javascript">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Example</title>
    <script type="text/javascript">
    /**
     *  Dynamically create form elements with incremental names.
     *
     *  @param tableId The ID of the table element.
     *  @param elemName The name of the element to be dynamically created.
     */
    function addRow(tableId, elemName) {
      if(!tableId || !elemName) return;
      
      // Grab hold of a reference to the table element and return from the 
      // function if no table element exists for the given table id.
      var tblElem = document.getElementById(tableId);
      if(!tblElem)  return;
      
      // Insert a new row at the end of the table, a new cell at the start
      // of that row and a new text node to the newly created cell.
      var newRow = tblElem.insertRow(-1);
      var newCell = newRow.insertCell(0);
      var txtElem = document.createElement("INPUT");
      txtElem.name = elemName + "[" + (tblElem.rows.length - 1) + "]";
      newCell.appendChild(txtElem);
      
      alert(document.getElementsByTagName("BODY")[0].innerHTML);
    }
    </script>
</head>
<body>
  <form id="frm" name="frm" action="#">
    <table id="tbl">
    <tbody>
      <tr id="dolly">
        <td><input name="hobby[0]"></td>
      </tr>
    </tbody>
    </table>
    <div>
      <input type="button" value="Append" onclick="addRow('tbl', 'hobby');">
      <br>
      <input type="submit">
    </div>
  </form>
</body>
</html>

Above code is working fine on FF but on IE7 name attribute is not set at all.
I had modified the above code to work on both the browsers.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Script-Content-Type" content="text/javascript">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Example</title>
    <script type="text/javascript">
    /**
     *  Dynamically create form elements with incremental names.
     *
     *  @param tableId The ID of the table element.
     *  @param elemName The name of the element to be dynamically created.
     */
    function addRow(tableId, elemName) {
      if(!tableId || !elemName) return;
      
      // Grab hold of a reference to the table element and return from the 
      // function if no table element exists for the given table id.
      var tblElem = document.getElementById(tableId);
      if(!tblElem)  return;
      
      // Insert a new row at the end of the table, a new cell at the start
      // of that row and a new text node to the newly created cell.
      var newRow = tblElem.insertRow(-1);
      var newCell = newRow.insertCell(0);
      //var txtElem = document.createElement("INPUT");
      
      //newCell.appendChild(txtElem);
	[B]newCell.innerHTML = "<input type='text' name='" + elemName + "[" + (tblElem.rows.length - 1) + "]'" + ">";[/B]
      
      alert(document.getElementsByTagName("BODY")[0].innerHTML);
    }
    </script>
</head>
<body>
  <form id="frm" name="frm" action="#">
    <table id="tbl">
    <tbody>
      <tr id="dolly">
        <td><input name="hobby[0]"></td>
      </tr>
    </tbody>
    </table>
    <div>
      <input type="button" value="Append" onclick="addRow('tbl', 'hobby');">
      <br>
      <input type="submit">
    </div>
  </form>
</body>
</html>

> Above code is working fine on FF but on IE7 name attribute is not set at all.

Just because the 'NAME' attribute is not shown in the alert doesn't mean that it is not set. Try to submit the form and take a look at the submitted query string i.e. the URL, it still submits the newly created form fields. Likewise the code works perfectly fine on the recent version of Opera.

Maybe something along the lines of the following snippet. Rigorous error checking omitted for brevity.

That was finer than my original addRow code! I added another function and a button to illustrate my problem.

function TryToGetName(tableId)
{
    var tblElem = document.getElementById(tableId);
    if(!tblElem)  return;
    
    // this is correct, with 3 buttons
    alert("total <inputs> = " + (document.getElementsByTagName("INPUT").length - 3));

    for(var i = 0; i < tblElem.rows.length; i++)
    {
        var hobby = document.getElementsByName("hobby[" + i + "]")[0];
  
        // But suppose I want to do validation and
        // value formatting with hobby.value,
        // IE will give a problem here.
       alert("hobbies["+i+"].value = " + hobby.value);
     }
}

The full version:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Script-Content-Type" content="text/javascript">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Example</title>
    <script type="text/javascript">
    /**
     *  Dynamically create form elements with incremental names.
     *
     *  @param tableId The ID of the table element.
     *  @param elemName The name of the element to be dynamically created.
     */
    function addRow(tableId, elemName) {
      if(!tableId || !elemName) return;
      
      // Grab hold of a reference to the table element and return from the 
      // function if no table element exists for the given table id.
      var tblElem = document.getElementById(tableId);
      if(!tblElem)  return;
      
      // Insert a new row at the end of the table, a new cell at the start
      // of that row and a new text node to the newly created cell.
      var newRow = tblElem.insertRow(-1);
      var newCell = newRow.insertCell(0);
      var txtElem = document.createElement("INPUT");
      txtElem.name = elemName + "[" + (tblElem.rows.length - 1) + "]";
      newCell.appendChild(txtElem);
      
      alert(document.getElementsByTagName("BODY")[0].innerHTML);
    }
    
function TryToGetName(tableId)
{
    var tblElem = document.getElementById(tableId);
    if(!tblElem)  return;
    
    // this is correct, with 3 buttons
    alert("total <inputs> = " + (document.getElementsByTagName("INPUT").length - 3));

    for(var i = 0; i < tblElem.rows.length; i++)
    {
        var hobby = document.getElementsByName("hobby[" + i + "]")[0];
  
        // But suppose I want to do validation and
        // value formatting with hobby.value,
        // IE will give a problem here.
       alert("hobbies["+i+"].value = " + hobby.value);
     }
}

    </script>
</head>
<body>
  <form id="frm" name="frm" action="#">
    <table id="tbl">
    <tbody>
      <tr id="dolly">
        <td><input name="hobby[0]"></td>
      </tr>
    </tbody>
    </table>
    <div>
      <input type="button" value="Append" onclick="addRow('tbl', 'hobby');">
      <br>
      <input type="button" value="getElementsByName('hobby[x]')" onclick="TryToGetName('tbl');">
      <br>
      <input type="submit">
      <br>
      
    </div>
  </form>
</body>
</html>

The getElementsByName seems to be flawed when working with dynamically added elements in IE. I guess adding elements by using innerHTML is the only way of making IE aware of the existence of new elements.

Anyways, try something simple like:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN"
            "http://www.w3.org/TR/html4/strict.dtd">
<html>
<head>
    <meta http-equiv="Script-Content-Type" content="text/javascript">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <title>Example</title>
    <script type="text/javascript">
    /**
     *  Dynamically create form elements with incremental names.
     *
     *  @param tableId The ID of the table element.
     *  @param elemName The name of the element to be dynamically created.
     */
    function addRow(tableId, elemName) {
      if(!tableId || !elemName) return;
      
      // Grab hold of a reference to the table element and return from the 
      // function if no table element exists for the given table id.
      var tblElem = document.getElementById(tableId);
      if(!tblElem)  return;
      
      // Insert a new row at the end of the table, a new cell at the start
      // of that row and a new text node to the newly created cell.
      var newRow = tblElem.insertRow(-1);
      var newCell = newRow.insertCell(0);
      var txtElem = document.createElement("INPUT");
      txtElem.name = elemName + "[" + (tblElem.rows.length - 1) + "]";
      newCell.appendChild(txtElem);
    }
    
    function getElementsThatStartWith(frmObj, str) {
      if(!str || !frmObj)  return;
      var elems = frmObj.elements, returnElems = [];
      for(var i = 0, maxI = elems.length; i < maxI; ++i) {
        var elem = elems[i];
        if(elem.name.indexOf(str) == 0) {
          returnElems[returnElems.length] = elem;
        }
      }
      return(returnElems);
    }
    
    function validateHobbies(frmObj) {
      var elems = getElementsThatStartWith(frmObj, "hobby");
      for(var i = 0, maxI = elems.length; i < maxI; ++i) {
        var elem = elems[i];
        alert(elem.name + ": " + elem.value);
      }
    }
    </script>
</head>
<body>
  <form id="frm" name="frm" action="#">
    <table id="tbl">
    <tbody>
      <tr id="dolly">
        <td><input name="hobby[0]"></td>
      </tr>
    </tbody>
    </table>
    <div>
      <input type="button" value="Append" onclick="addRow('tbl', 'hobby');">
      <br><br>
      <input type="button" value="Get All Hobbies" onclick="validateHobbies(this.form);">
      <br><br>
      <input type="submit">
    </div>
  </form>
</body>
</html>
Comments
Very professional programmer

Thanks to everyone with the help and especially SOS for the neater code suggestions. I think i can solve my problems from here on already.

anyway, nice efficient for loop here:

for(var i = 0, maxI = elems.length; i < maxI; ++i) { ... }

I dont understand you guys. There is a easier way to send array of elements.
Check this out:

<input name="something[]" />
<input name="something[]" />
<input name="something[]" />

And now to add/delete elements you can set id parametr. It works in IE/Fx very well.

I dont understand you guys. There is a easier way to send array of elements.
Check this out:

<input name="something[]" />
<input name="something[]" />
<input name="something[]" />

And now to add/delete elements you can set id parametr. It works in IE/Fx very well.

In any case, your method is indeed clever, which I just learnt recently. But the problem is illustrated below:

<script type="text/javascript">
function AddRow()
{
  var hobby = document.getElementsByName('hobby[]');
  alert(hobby.length);
  
  var formObj = document.getElementById('form_form');
  var i = document.createElement("input");
  i.name = "hobby[]";
  formObj.appendChild(i);
  
  // doesn't work in IE when it should
  var hobby = document.getElementsByName('hobby[]');
  alert(hobby.length);
  hobby[hobby.length - 1].value = "I am the latest input box";
  // this makes validation problematic
}
</script>

<form id="form_form" method="POST">
<input type="button" value="Add Row" onclick="AddRow();" />
<input type="submit" value="submit" />
<input type="text" name="hobby[]" />
</form>
This question has already been answered. Start a new discussion instead.