ColdFusion in Context: Use Identically Named Fields

Suppose you want to let the user work with multiple rows of data at once but don't want to assign a separate set of fieldnames for each row. When you use the same name for multiple fields and submit the form using the post method, the form passes the field once with all the non-empty values separated by commas in a single string. Empty values won't even get a placeholder. This means that if you list 10 items, provide 10 quantity fields for the user to fill in, and the user only fills in 4, you won't know WHICH 4 items the quantities go with. This isn't ColdFusion's fault; it's the way forms work.

So what do you do? If you force a value (a zero, for example) for every field, then users who click on a field using a mouse instead of tabbing to the field will have to backspace to make an entry. Further, they might change their minds after backspacing and leave the field empty. If some fields are left empty, then you run into the problem above. However, there's a better way, as this tip will demonstrate.

Javascript has two ways to access a field: by name and by element number. It can loop through every field in a form and work with each name and value it finds, even empty values. You can therefore use javascript to create the comma-separated list you need. This tip simulates receiving items and rows from a database. The assumption is that you had ColdFusion create a list of item names and are expecting javascript to create a corresponding list of quantities from user entries. The form itself consists of a hidden string of item names, rows each containing an item name and a quantity field, and display fields proving a one-to-one correspondence between item names and quantities when the user is done.

Loop Through the Form

Starting with the top of the form - call it fieldnames.cfm - create a script that you'll call to make the string. Because you don't want it to execute before you're ready, put it inside the head of the document. The function begins by emptying the field that will be used later to display the string of quantities. It then defines an empty string and an empty separator.

<head>
<script language="javascript">
function pack() {
  // Reset the display
  document.myForm.Quantities.value = '';
  var myList
  myList = '';
  var sep
  sep = '';

The for loop walks through every element in the form. If the element's name contains "Qty", then it sets myList equal to the current contents of myList (which starts off empty), the separator (which starts off empty), and the value of the element. It then sets the separator to a comma so that subsequent values will be preceded by a comma.

  for (i = 0; i < document.myForm.elements.length; i++) {
    if ((document.myForm.elements[i].name.indexOf('Qty') > -1)) {
      myList = myList + sep + document.myForm.elements[i].value;
      sep = ',';
    }
  }

The script and page header end with two assignments. The list you've been building gets copied to the Quantities field for display and a hidden list of item names gets copied into the Names field for display.

  document.myForm.Quantities.value = myList;
  document.myForm.Names.value = document.myForm.namelist.value;
}
</script>
</head>

Give Instructions and Create the Form

The body of the page needs to describe what to do and to accept user input. After the form begins, code that would normally be generated by ColdFusion from a database is inserted. It begins with a hidden field containing a string that holds an entry for each item. It then displays a row for each item and a place to indicate its quantity. This portion would normally be generated by cfoutput tags driven by a query. You're looking at an approximation of the result that would be received by the client browser. The form (and page) ends with appropriate buttons and some fields that will display the strings to prove that even the empty fields receive an entry using this method.

<body>
Enter a quantity (or leave it empty) for each item.

When you press the evaluate button,<br>
the hidden list of names supplied by ColdFusion
and the list of quantities supplied by javascript
is shown to prove a one-to-one correspondence between them.
<p>
<form name="myForm" action="fieldlist.cfm" method="get">
<!--- In reality, ColdFusion would generate
the following code from a database --->
  <input type="hidden" name="namelist" value="Aardvark,Beaver,Cougar,Dachshund">
  Aardvark <input type="text" name="Qty" value="" size="4">
  Beaver <input type="text" name="Qty" value="" size="4">
  Cougar <input type="text" name="Qty" value="" size="4">
  Dachshund <input type="text" name="Qty" value="" size="4"><br>
<!--- End of "generated" code --->
<input type="button" name="doit" value="Evaluate" onClick="pack();">
<input type="reset" name="nobody" value="Clear All"><p>
(List of Names <input type="text" name="Names" value="" size="40">)<br>
(List of Quantities <input type="text" name="Quantities" value="" size="40">)
</form>
</body>

Use It

To see what it does, copy all this code to fieldlist.cfm and execute it. It doesn't have a submit button; so, you can continue to add and change values to see the result. When you extend the concept, parse the Quantities string you've just built, not the Qty string the form passes by default. On the server (or on the client if you have a need to do so), loop through both Names and Quantities at the same time to associate each item with its quantity. =Marty=