wForms - Server-side handling of the Repeat Behavior (part 2)
The Repeat behavior is certainly the most powerful functionality of the wForms extension and enabling it in a web form is dead simple (class=’repeat’ anyone?). Processing the form submission is trickier though, but the real difficulty with repeated groups arises when you want to populate a form with previously submitted data. You basically need to re-engineer server-side what wForms does client-side.
The Form
Let’s start with a simple form and let’s make the fieldset repeatable by using wForms’ ‘repeat’ class.
<form action="">
<fieldset id="myfieldset" class="repeat“>
<label for=”field1″>Label 1: </label>
<input type=”text” id=”field1″ name=”field1″ />
<label for=”field2″>Label 2: </label>
<input type=”text” id=”field2″ name=”field2″ />
</fieldset>
</form>
Submitted Data
Now, assuming that this form was previously submitted with 3 rows, the data collected on the server contains the following fields:
| Field Name | Field Value | Comment |
|---|---|---|
| field1 | value1… | original row |
| field2 | value2… | |
| field1-2 | value3… | second row |
| field2-2 | value4… | |
| field1-3 | value5… | third row |
| field2-3 | value6… | |
| myfieldset-rc | 3 | row counter |
Populating back the form
In order to show the form back to the user, you need to :
- Loop 3 times over the <fieldset> element.
- Set the value of each field.
- Appends the row index suffix to the id, name and for attributes for every tag in the second and third rows (the first row is always left unchanged by wForms).
- Change the class from ‘repeat’ to ‘removeable’ (sic) for the second and third rows.
- Create the hidden counter field. The name of this field is constructed by adding ‘-RC’ to the id of the tag with the ‘repeat’ class (here ‘myfieldset’).
If the form is correctly set up, wForms will be able to carry on from there, allowing adding more rows or removing the existing ones.
Sequence gaps
Now, as I mentioned previously, the -RC field in wForms does not exactly behave like a row counter. It indicates the highest row index reached. If the user deleted a row before submitting the form, you’ll end up with a gap in the sequence that you need to accommodate for. In the loop logic, you can tell if the row was deleted if you can’t find any name/value pair in your submitted dataset for the given row index.
Code Sample (PHP)
Note: Updated on June 15th 2007.
<?php
$max = (int) $_POST["myfieldset-RC"];
for($i=1;$i<=$max;$i++) {
if($i==1) {
$repeatclass = "repeat";
$rowIndex = "";
}
else {
$repeatclass = "removeable";
$rowIndex = "-".$i;
}
if(isset($_POST["field1".$rowIndex]) && isset($_POST["field2".$rowIndex])) { // account for sequence gap.
?>
<fieldset id="myfieldset<?php echo($rowIndex)?>" class="<?php echo($repeatclass)?>">
<label for="field1<?php echo($rowIndex)?>">Label 1: </label>
<input type="text" id="field1<?php echo($rowIndex)?>" name="field1<?php echo($rowIndex)?>" value="<?php echo($_POST["field1".$rowIndex])?>" />
<label for="field2<?php echo($rowIndex)?>">Label 2: </label>
<input type="text" id="field2<?php echo($rowIndex)?>" name="field2<?php echo($rowIndex)?>" value="<?php echo($_POST["field2".$rowIndex])?>" />
</fieldset>
<?php
}
}
echo "“;
?>
Result
Update: Comments are now closed for this post, but you can go to the wForms forum if you have any question or comment. Thanks !
August 30th, 2005 at 9:00 pm
Okay, now, on showing errors from server side processing.. How should one go about this for Repeat fields..
Jay
September 1st, 2005 at 1:23 am
Jay.. I suppose you should display the form as the user submitted it (as explained in this post) and add the error message(s) where appropriate.
It’s probably a good idea to be consistent with wForms treatment of client-side errors. Add the ‘errFld’ class to the field in error, and wrap the error message in a tag with the ‘errMsg’ class.
Ex:
<p class=”errMsg”>Please correct the following: </p>
<input type=”text” class=”errFld” value=”something” … />
September 1st, 2005 at 11:28 pm
Hi,
. It would convince the newbies
.
.
I few improvements to wForms:
- use some icons for “add a row” and “remove” - it would look better and the text from the link wouldn’t flow on the next text row(as it’s now in some cases).
- make a link in menu for ‘wForms’ like the one for Form Builder . At the moment one needs to dig in project news, documentation and archive to find things about wForms. I think there should be one big page for it, with links too everyhing what’s related.
- add a page “who is using wForms”
- put a JSP/Servlet example too (not just PHP) - many think it’s PHP only (even if it’s only on the client)
Klaus.
September 2nd, 2005 at 4:30 am
Klaus, regarding the icons add/remove row, you can already use an CSS image replacement technique. I’ll try to post some details about that.
Your other suggestions are excellents. I’ll try to put more code samples for ASP, but I’m not familiar with JSP. If you have some code to share, please send me an email (cedric at formassembly dot com).
December 16th, 2005 at 11:54 am
Great starter article, although I am getting stuck on repopulating the form during the second visit to the page. I’ve created a test page at http://www.supersaiyan.com/RepeatTest.asp — it does a bit of validation to ignore empty rows, make sure URLs are formatted properly, yadda yadda yadda.
The problems are occuring during my second visit to the page. Upon returning to the page for a second visit, I add a hidden variable (the so-called “-RC” field value) to the form — you can see it in the source code, just beneath the form tag declaration. But when I submit the page again, it still automatically creates another identically-named field behind the scenes. The end-result: there are two (comma-delimited) values passed to the same variable, which means I can’t interpret it as an integer value anymore.
Any chance you can help me out? I’m an experienced ASP developer (8+ years) and will gladly help build up your library of ASP code samples… I just need help figuring out what fundamental idea I’m failing to understand.
December 16th, 2005 at 11:39 pm
Your server sees 2 fields with the same name and concatenate their values in a comma separated list.
Now, if wForms recreates the counter field it’s because it failed to recognize the one you provided as such. Make sure the *id* attribute is set, the name attribute is not enough.
In your case you should have:
<input type=”hidden” name=”WeblinkRepeater-RC” id=”WeblinkRepeater-RC” value=”3″ >
December 16th, 2005 at 11:52 pm
Excellent! I’ll try this as soon as I get home Thank you _so_ much for responding (at all) and especially for doing so quickly. I’m using wForms in a web application I’m building, primarily because the Repeat class allows them to do on a single page what would normally take [n] round-trips to accomplish.
Once the site launches, I’ll clean up some of the more salient code and post it somewhere — either here or on my website within public view. Cheers!
January 6th, 2006 at 12:50 pm
After a minor change in wforms.js it’s much easier to handle $_REQUEST on the server side.
//From::
// Prepare id suffix
var suffix = “-” + rowCount.toString()
//To:
// Prepare id suffix
var suffix = “[” + rowCount.toString() + “]”;
you get an array of fields values.
January 6th, 2006 at 11:44 pm
Chris, thanks for the tip. I should point out though that it only works for PHP.
January 16th, 2006 at 6:22 pm
hello chris.
I make changes as u proposed.Strange thing - $_POST doesnt include original fields from repeat TR - only copies.Why??
February 7th, 2006 at 4:03 pm
hi nikss.
To be honest u need to make much more changes to make it work.
U also have to rewrite removeRepeatCountSuffix function and some minor changes.
If u think it’s still worth to do it, i’ll post my code somewhere.
February 26th, 2006 at 12:17 am
I’m having a problem with actually retrieving the -RC field. I copied and pasted the code as is, and only changed the somename and someid fields. I can access the extra fields using the somename-2, 3, etc.
But for some reason I can’t access the someid-RC value.
Any ideas?
February 26th, 2006 at 12:42 am
Miq.. can you send me your code (cedric at formassembly dot com) or post in the forum:
http://formassembly.com/forums/
I’ll check it out. Thanks.