logo

Storing lots of input fields in one list

How many times have you created a form that has a collection of fields that all gather information that is related. What I mean by this is something similar to the form shown in the image below. Here, all the fields are related by the fact that they gather data for a list of "Results" and have field names like Results1, Results2, Results3 etc.

Image

In design mode a form like this will look something like the screen below. Designing it is a laborious task of adding field after field. Changes to the form can be just as time consuming.

Image

It is not uncommon for forms like this to have groups of fields where there are 30, 40, 50 or more in each. Nothing wrong with this in itself. It is just that whenever I find myself doing it there is always that nagging voice at the back of my head saying "What are you doing? There must be another way!".

Is there another way?

There is indeed. What I'm about to describe makes use of this little known fact: you can have a number of text-input fields in a web form all with the same name. Consider the HTML from a form like below:

Result 1: <input type="text" name="Results"><br />
Result 2: <input type="text" name="Results"><br />
Result 3: <input type="text" name="Results"><br />
Result 4: <input type="text" name="Results"><br />

I'm not sure whether or not this is "legal" in the HTML specification but Domino doesn't have a problem with it, as long as there is a Notes Field on the form with the same name. The trick is to hide this Notes field and make it Multi-Valued. When the form is submitted Domino adds the value from each of the individual input fields as a new entry in the list in the Notes field.

So, how would we design a form like this in Domino Designer. Well, the screen below shows a table that contains a "Results List". In it we have used pass-thru HTML to create an input field with the same name in each cell.

Image

Now let's take another look at the first image that shows the form as it will appear in the browser. Notice that, for the sake of demonstration, I have added values to some of the fields. Let's see how Domino stores this data. After submitting the above form and opening up the Document Properties for the resulting document we see something like this:

Image

Notice that there is only one field called Results stored in the document rather than an ugly looking list of fields, all with the similar names. The values stored in this field match those entered, with blank entries where we left the input elements empty. We could use @Trim in the field's Input Translation to remove them. However, as we shall later, these blanks are an essential part of the way this will work.

Wait a minute, that won't work!

Indeed, the more astute amongst you, who haven't already dismissed this as tosh and stopped reading, may well have noticed there is a problem with the above method. It's all very well creating all these empty input fields when they are on a new form but what happens when we open the newly created document in read mode!? In the above case all we will get is a set of empty fields and no data. The field that is storing the information is hidden and the design doesn't take account of displaying it.

What we need to do is take account of three different scenarios, each involving the use of different HTML:

  1. Creating a New Document
  2. Reading a Document
  3. Editing a Document

So, how else can we do it?

First thing to do is replace the table with a Computed Text area. We can then use @Formulae to dynamically create the HTML depending on the context that the document is in. Take a look at the form as it appears in the screen-shot below:

Image

Notice that we are creating the original table ourselves* using HTML. We now need a formula that will send the right HTML to the browser at the right time. We are going to use this formula in the computed text area:

REM "This formula dynamically creates input fields";

REM "Make sure you have a multi-value Notes field with the same name as the following variable";
FieldName := "Results";
FieldCount := 26;
FieldLabel := "Result ";
FieldValues := Results;

ZeroToNine := "0" : "1" : "2" : "3" : "4" : "5" : "6" : "7" : "8" : "9";
ZeroToNinetyNine := ZeroToNine *+ ZeroToNine;
ZeroToFieldCount := @Subset( ZeroToNinetyNine; FieldCount);

REM "Create the HTML";
HTML :=
@If(
@IsNewDoc;
FieldLabel + @Text( @TextToNumber(ZeroToFieldCount) + 1 ) + "</td><td><input type=\"text\" name=\"" + FieldName + "\">";

@IsDocBeingEdited;
FieldLabel + @Text( @TextToNumber(ZeroToFieldCount) + 1 ) + "</td><td><input type=\"text\" name=\"" + FieldName + "\" value=\"" + FieldValues + "\">";

FieldLabel + @Text( @TextToNumber(ZeroToFieldCount) + 1 ) + "</td><td>" + FieldValues
);

REM "Send the HTML to the browser";
@Implode( "<tr><td>" + HTML; "</td></tr>" + @NewLine )


Don't worry it's not quite as complicated as it first appears. Let's examine the code piece by piece:

FieldName := "Results";
FieldCount := 26;
FieldLabel := "Result ";
FieldValues := Results;

The first four lines simply set up a few constants. This is the only part you should need to change between uses unless you want to make changes to the HTML attributes of the individual rows and cells.

ZeroToNine := "0" : "1" : "2" : "3" : "4" : "5" : "6" : "7" : "8" : "9";
ZeroToNinetyNine := ZeroToNine *+ ZeroToNine;
ZeroToFieldCount := @Subset( ZeroToNinetyNine; FieldCount);

This is the key part of the formula. The Permuted Addition operator (*+) acts on the two lists, pairing every possible combination of their values. The resulting list has an element for each pairing in the following order: list 1 element 1 paired with each element in list 2, list 1 element 2 paired with each element in list 2, and so on through the last element in list 1. The result is a list of 100 items: 00, 01, 02, 03 through 99. The final variable has the same number of items as the number of fields we require.

HTML :=
@If(
@IsNewDoc;
FieldLabel + @Text( @TextToNumber(ZeroToFieldCount) + 1 ) + "</td><td><input type=\"text\" name=\"" + FieldName + "\">";

Here the form is being newly created and all we need to send to the browser is the empty fields. To do this we assign the HTML variable with a list of rows equal to the ZeroToFieldCount variable. The beauty of the formula language it that we can add HTML to every item in a list simply by permuting each.

@IsDocBeingEdited;
FieldLabel + @Text( @TextToNumber(ZeroToFieldCount) + 1 ) + "</td><td><input type=\"text\" name=\"" + FieldName + "\" value=\"" + FieldValues + "\">";

When the document is in edit mode it is slightly different to a new form. We now need to assign the stored data to the "value" attribute of the inputs. This is why the blank entries were so important earlier on. This way the values are correctly assigned to the right rather than Result1 having Result2's value because Result1 was originally blank.

FieldLabel + @Text( @TextToNumber(ZeroToFieldCount) + 1 ) + "</td><td>" + FieldValues
);

Finally when the form is in read mode we have no need for the input fields and simply send the data to each cell.

REM "Send the HTML to the browser";
@Implode( "<tr><td>" + HTML; "</td></tr>" + @NewLine )

The last step of the formula returns the HTML to the browser. We need to implode each value so that we return a string rather than a list. It is in this implode action that we append the HTML to close the last cell and then the row. The @NewLine is purely to keep the HTML source tidy.

But what about back-end access to this data!?

So we've got a document and it's storing all the values but what about when we need access to this data. This depends on how you want to get access to the values.

If you were using Formula language you can get access to any particular value with the following line:

REM "Get value stored for Result 6";
@Subset( @Subset( Results; 6); -1);

If you were using LotusScipt then you could use code similar to the following:

Dim results as Variant
Dim result6 as String
results = doc.Results
'Note: results is a zero-based array
result6 = results(5)

Fancying yourself as a true developer and using Java you would get the 6th Result using:

Item Results = dc.getFirstItem("Results");
String Result6 = (String)Results.getValues().elementAt(5);

When using JavaScript we need to send an array of values to the browser. We can do this with the following formula in the HTMLHead:

"<script>" + @NewLine +
"<!-- " + @NewLine +
"var Results = new Array();" + @NewLine +
@Implode( "Results[Results.length] = " + Results + ";" ; @NewLine) + @NewLine +
"// -->" + @NewLine +
"</script>"

Then any JavaScript functions can access value 6 using the following line:

alert( Results[5] );

if the document is in edit mode then JavaScript can access the values directly, using this syntax:

document.forms[0].Results[5].value


In conclusion

Yet again I have discussed a technique that, at the end of the day, is probably of no use to man nor beast. Admittedly it may make your life easier and your form tidier but it also has a few things about it that will stop some people from using it. Nevertheless, as with most of articles, I use them to try and get people to read between the lines and pick up on little techniques that, when combined, make Domino an extremely powerful tool....

One possible use of the method is in an Address Form where you have Name, Street, Address Line 1, Address Line 2 etc. Here you could just store it all in one field called Address!




*If you haven't guessed already this approach is only applicable to web-only applications. Sorry but that is all I seem to do nowadays. Can't remember the last time I used the Client ;)

Feedback

  1. Definite potential...

    This is one of those items that crosses my mind from time-to-time, but never made it to my "experiment list." At first glance, I do think this will be useful in a project I will be working on this summer. I'll let you know how it works out.

  2. Great, but problem with a 2nd input column

    This is great, but I had a problem when I added a 2nd input column. Same idea as for the first input column but in the second one I'm writing to another hidden multi value field. I expect to get two lists, one for each column of data entry. Instead I only get the last value entered for each field. Any ideas why?

    1. Re: Great, but problem with a 2nd input column

      Hmm, not sure I understand what you have done here.

      Have you created another hidden multi value field with a [<i>different</i>] name to hold this second list of values? Have you changed the name of the inputs created by the second column?

      The fact that you only get the last values suggests that you haven't made the fields Multi-Value.

      Jake -CodeStore

      Hide the rest of this thread

      1. Re: Great, but problem with a 2nd input column

        What I did was create two hidden multi value text fields, one called Col1Values and one called Col2Values. Then I created a table with two columns for input. The first column contains the pass through HTML {<input type="text" name="Col1Values">} in each row. The second column contains the pass through HTML {<input type="text" name="Col2Values">} in each row. Input is accepted without error from the web, but the result is a single value in each of the hidden multi value fields. What is stored is the value in the last row for each column.

        What I suspect might be happening is that Notes appends or ?replaces? values for fields depending on the order of the name/value pairs it receives. Successive pairs with the same name cause their values to be appended to the named field, but if the name is different from the previous pair then the value for that ?new? named field will start with the value in that current pair, even if the name had occurred before. In a single column table all the name/values for the one name are passed one after the other. In a two column table the order is likely to be column 1 name/value, column 2 name/value, column 1 name/value etc. That could explain what I've seen. In fact, I was able to get a subset of a column list by reducing the number of inputs for the other column, which put the last inputs for the longer column in succession again.

        1. Very strange

          Just tried it myself and indeed it does only save the last two values. Very odd.

          I think you are on the right lines with your reasoning. I'm going to have to look deeper in to this and see if there is a solution - I'm intrigued.

          For the time-being I guess the only fix is to remove them from the columns. I imagine this isn't acceptable though....

          Leave it with me, Jake -CodeStore

    2. The problem and the solution

      Ok, I've done a bit of investigating and here is what I learnt - using this [<a href="http://www.ethereal.com/">handy little tool</a>]. The first thing I did was look at what was being sent back to the server when you create two columns of fields as you described. Here is the TCP Packet information: [<br clear="all" /><code style="color:006600;">] POST /development/jakeh/personal.nsf/multival?OpenForm&Seq=1 HTTP/1.0 Referer: http: //uk-n5uata-04/development/jakeh/personal.nsf/multival Accept-Language: en-gb Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0) Host: uk-n5uata-04 Content-Length: 333 Connection: Keep-Alive Pragma: no-cache

      __Click=ff0b821a3629605b80256a80006ca325%2F%24Body%2F0.8C8&Col1Values=1first&Col 2Values= &Col1Values=&Col2Values=2second&Col1Values=1third&Col2Values=&Col1Values= &Col2Values=&Col1Values=&Col2Values=&Col1Values=&Col2Values=2sixth&Col1Values= &Col2Values=&Col1Values= &Col2Values=&Col1Values= &Col2Values=&Col1Values=1last&Col2Values=2last [</code>]

      The bottom section show that the field names ("Col1Values" & "Col2Values") and values are being sent as alternatin pairs for each column as the form is collated left to right and top to bottom. The next thing I did was replace the two columns with one field called "MultiValField". I made this a Checkbox and then a Multi-Select keyword list. On both occasions the post was as below: [<code style="color:006600;">] POST /development/jakeh/personal.nsf/multival?OpenForm&Seq=1 HTTP/1.0 Referer: http: //uk-n5uata-04/development/jakeh/personal.nsf/multival Accept-Language: en-gb Content-Type: application/x-www-form-urlencoded User-Agent: Mozilla/4.0 (compatible; MSIE 5.5; Windows NT 4.0; HSBC Asset Management) Host: uk-n5uata-04 Content-Length: 122 Connection: Keep-Alive

      __Click=7293d43d9cd32c7880256a81003218e5%2F%24Body%2F0.196&MultiValField=2& MultiValField=3&MultiValField=5&MultiValField=7 [</code>] This is how I imagine that Domino expects the data for multi value fields to be formatted - one after the other. This is the format that is rendered when we have only one column on the form hence why the idea works.

      The problem is that when we format the columns in a table the browser sends the data from each column of each row one at a time. Domino then stops processing values for a field if it encounters a field with a different name. If it then comes across the same field later on it starts to interpret the values from fresh.

      [<b>Solution:</b>]

      The trick here is that we need to layout our form in such a way that each field gets sent all in one go. The easiest way I found of doing this for the two column problem was to put each column in a new table. So all we need is a one row/two column table. In the first cell add a one column table with as many rows as you need and then another one column table in the second cell with the same number of rows. Add the fields to these tables. Now, when the browser submits the form it goes through each table and cell one by one. The fact that the cell contains a sub table means that this gets processed before the cell containing the second column.

      We could also do away with the sub table and place the column in each cell by seperating the fields with a <br> tag.

      Hope all this helps, Jake -CodeStore

  3. A word of warning

    It doesn't work if "Generate HTML for all fields" is selected in the form properties

    1. Re: A word of warning

      In fact when you enable Generate HTML for all fields, your hidden field is store at the end of your HTML and so the index of this field is not the first one but the last one. That is why it is not working.

      The solution The multi-value field must be created before your set of html fields and it works. Do not hide it in Notes. Just hide it with Type="Hidden" in the HTML attributes of the field.

  4. Something to be aware of... radio buttons

    This code is great... Unfortunately, when trying to implement it, I found that this method does not work when trying to use radio buttons...

    The HTML to construct a radio button is something like below... (Considering you are asking a question and have lined them up in a table)

    <TR> <TD>Do you want to develop in Lotus Notes?</TD> <TD> <INPUT TYPE=radio NAME="ans1" VALUE="Yes"> <INPUT TYPE=radio NAME="ans1" VALUE="No"> </TD> </TR>

    This will then create a "single" radio button with "Yes" and "No" as the two options...

    When you implement the method in this thread, it works great if you use text fields, but when throwing in radio buttons and checkboxes, you will notice that when you select an option for another radio button down the line, it will deselect the chosen option before it. You know, that is what is supposed to happen.... radio buttons only allow for one option per field. When you name all of the HTML fields the same thing and use multiple radio buttons, it thinks they are all options in the same field. It just, I don't know....stinks that you have to name all the fields the same thing for this to work.

    I guess what I am getting at is hoping that this can be revisited. I am trying to create a user-populated form. Basically, they create their questions and options (for radio buttons and checkboxes) in a document, and I then create the form by importing the HTML that I dynamically generated in each document to construct the questions on the user form. I can do all this with LotusScript, I can even build the field names on the back-end of the document (

    For i=1 To dc.Count Dim qitem As New NotesItem(doc, "Qual" & i , "") Next

    ) which match the field names of the dynamically generated HTML field names, and then present it to the user so they can fill out the form - so technically they are there. The only problem is that if they are not on the actual underlying form, when you try and submit it you get all kind of errors and the document is never saved.

    Jake, you are an incredible developer and your ideas have helped me out many times and I guess I am wondering if you can revisit this and maybe see if you can help me figure out a way to submit a form with dynamically generated HTML fields and write them to the backend document.

    If this is a pipe-dream let me know that too so I can stop smashing my head against the wall.

    Thank you again for all of your wonderful code and ideas....keep up the outstanding work.

      • avatar
      • Sam
      • Mon 1 Jul 2002

      Re: Something to be aware of... radio buttons

      I tried to do the same thing with radio buttons, but found that I was handcuffed by having to use the NAME property. However, I was able to use drop down fields (e.g. <SELECT><OPTION>...</SELECT>) quite effectively for the same purpose. In fact, I use some JavaScript to dynamically generate drop-down choices depending on what the user had chosen before, so it actually worked better than radio buttons would have.

      Sam

  5. not working with multivalue field of type Number

    Hi Jake,

    I'v tried this solution with a numberfield, but strangely the values are save as a textlist. The server doesn't even raise an error !

    Any ideas?

    regards,

    Tom

      • avatar
      • Jake Howlett
      • Fri 28 Mar 2003

      Re: not working with multivalue field of type Number

      Sounds strange Tom. Have you set the actual field on the Notes form to be of type number? Obviously the field type on the browser has to be text as HTML doesn't recognise the number type. Try using @TextToNumber(fieldname) in the field's Input Translation formula and see what happens. Jake

      Show the rest of this thread

  6. how do you do this in LotusScript?

    i'd like to know how to do this in lotusscript with checkboxes. i don't know the right syntax for lotusscript. i know you need to use print but after that?

    hope somebody will help.

    Thanks, Chiqui

      • avatar
      • paul
      • Wed 15 Mar 2006

      list with number, only words input

      Hello I would like to have a list ( 1- Toronto, 2- Montreal... ) to appear when we tab to the approach field, then typing the number like 1 , on the field will be save Toronto. This is in order to make faster the input of data, in the list we have around 59 cities, some of them have similar names, the drop down list will take to long, therefore the numbering is faster for the data entry cleark. Thanks for the help Paul

  7. DON'T interleave your fields or it won't work!

    So I spent half a day figuring this out, so learn from my pain!

    If you want to input DIFFERENT multiple field then you CANNOT interleave them.

    For example, FieldA FieldDB FieldA FieldB will only take the last instance of Field A and Field B.

    You must set your form so that the natural sequence of fields is FieldA FieldA FieldB FieldB which can be a real pain (and quite a limitation) if you wanted to say enter a PART NO followed by QTY for 50 different items (eg a quick order list).

    I only managed to get round it by placing the items in the correct order in a table so that the table contained the label in the first column with columns two and three containing the SAME field thus: PART NO: PARTNO PARTNO QTY REQ: PARTQTY PARTQTY

    but really I would liked to have unlimited entries; this way I am limited to the width of the screen.

    If anyone has found a workaround please post here!

    I guess it' easy to see wHY this happens, it's just a pity either HTML and/or Domino doesn't work differently.

    Basically the submit string contains something like PARTNO=123456&PARTNO=34567&PARTQTY=3&PARTQTY=20 so that all the items are concatenated together. If you interleave the fields then it "forgets" the first lot of values. Now is this domino just playing silly buggers or a limitation of HTML?

    I guess as we're using an anomoly of Domino I shouldn't moan too much, but still...!

    1. Re: DON'T interleave your fields or it won't work!

      Take a look at http://searchdomino.techtarget.com/tip/0,289483,sid4_gci1236083,00.html . I believe this should answer your questions. In this solution, no Notes fields are required AT ALL, just the one that keeps track of the other values!

      Leonard

Your Comments

Name:
E-mail:
(optional)
Website:
(optional)
Comment:



Navigate other articles in the category "Forms"

« Previous Article Next Article »
Printing with Page Breaks   Creating a simple search box

About This Article

Author: Jake Howlett
Category: Forms
Keywords: inputs; multi value;

Options

Feedback
Print Friendly

Let's Get Social


About This Website

CodeStore is all about web development. Concentrating on Lotus Domino, ASP.NET, Flex, SharePoint and all things internet.

Your host is Jake Howlett who runs his own web development company called Rockall Design and is always on the lookout for new and interesting work to do.

You can find me on Twitter and on Linked In.

Read more about this site »