homepage Welcome to WebmasterWorld Guest from
register, free tools, login, search, pro membership, help, library, announcements, recent posts, open posts,
Become a Pro Member

Home / Forums Index / WebmasterWorld / New To Web Development
Forum Library, Charter, Moderators: brotherhood of lan & mack

New To Web Development Forum

How to insert input fields in a form with a new line button

 3:35 am on Jan 30, 2009 (gmt 0)

I am building an order form of sorts and have been searching for days on how to add a new line on my form by clicking an "Add More Lines" button. I have an html form that is like an order form. It shows only 5 rows for input. i.e. part#, description, quantity, price etc... with a running total at the bottom. I need a way for the user to be able to click a button and add a new line or even delete a line if needed while still being able to keep a running total. These new lines would also have to be labeled because the information will then be submitted to a Mysql database.

Please help.



 3:39 pm on Jan 30, 2009 (gmt 0)

Welcome aboard cffrost2, while you could do something like this with Javascript, this would make it Javascript dependent and you'll still need to screen and process the new lines server side. So the best approach is something with a server-side script (perl, php, asp....).

If the variable/form value "add_line" exists, you'd re-generate the html form with an added line, and keep all the submitted values intact. If it has a "delete" marker for the line, remove the line.

function form() {
$output = '
<form method="post" action="yourscript.cgi/php/asp">
<input type="checkbox" name="delete_1" id="delete_1"> Delete
<input type="text" name="price_1" id="price_1">
if ($form_values{'add-form'}) {
$form .= (add another line) .....
$form .= (submit and </form>)
return $output;

[edited by: eelixduppy at 6:36 am (utc) on Feb. 6, 2009]
[edit reason] disabled smileys [/edit]


 5:12 pm on Jan 30, 2009 (gmt 0)

Thanks. Let me just say this is a great site. Thanks for your reply. I'm new to all of this so I'll need to take it slow. Seems like just what I need. Could you be a bit more specific as to how I would put it in action?

For example, one form row i use is:
<tr class="ServiceDetailRow" id="Row1">

<td id="ServiceDetailColumn"><input type="button" onclick="reset(this)" name="Button" value="-" /></td>
<td id="ServiceDetailColumn"><input type="button" onclick="displayRow2()" name="Button" value="+" /></td>
<td id="ServiceDetailColumn"><input name="Part1" type="text" id="Part1" size="15" /></td>
<td id="ServiceDetailColumn"><input name="Desc1" type="text" id="Desc1" size="100" /></td>
<td id="ServiceDetailColumn"><input name="Qty1" type="text" id="Qty1" size="4" /></td>
<td id="ServiceDetailColumn"><input name="Price1" type="text" id="Price1" size="7" /></td>
<td id="ServiceDetailColumn"><input name="ExtPrice1" type="text" id="ExtPrice1" size="7" /></td>

which as you can see calls a javascript function to simply add the "hidden" row. Like you said, I would need 100 hidden rows and a lot of code. Then if the user needs to delete a row, more code. I think your example would do what I need. I just need help implementing it.

Again, thanks very much


 3:55 pm on Jan 31, 2009 (gmt 0)

Well, it's a bit more complex than a single post, but I can give you logic ideas to work with.

For example (as said, I would not do this with Javascript) it doesn't have to be "a lot" of code. I notice all your "lines" are appended with a number. This kinda makes it easy. Start with a variable to track the line numbers:

PHP-ish/perl-ish code follows

$rownums = isset($data['rownums']))?$data['rownums']:1;
$rowcontent = '';
if ($data['add-row']) { $rownums++; }
else { process_order(); } // see comment below

Then in your functions to generate the rows, dynamically create the form names/id's:

for ($i=1;$i<=$rownums;$i++) {
$partname = 'Part' . $i;
$descname = 'Desc' . $i;
$qname = 'Qty' . $i;
$pricename = 'Price' . $i;
$extname = 'ExtPrice' . $i;
// Maintain existing values in the form, or not.
$data[$partname] = (isset($data[$partname]))?$data[$partname]:'';
$data[$descname] = (isset($data[$descname]))?$data[$descname]:'';
$data[$qname] = (isset($data[$qname]))?$data[$qname]:'0';
$data[$pricename] = (isset($data[$pricename]))?$data[$pricename]:'0.00';
$data[$extname] = (isset($data[$extname]))?$data[$extname]:'0.00';
// Which results in Part1, Desc1 . . . etc., and prepopulated or default values.
$rowcontent = '
<td id="ServiceDetailColumn"><input type="text" name="' . $partname . '" id="' . $partname .
'" size="15" value="' . $data[$partname] . '"></td>
<td id="ServiceDetailColumn"><input type="text" name="' . $descname . '" id="' . $descname .
'" size="100" value="' . $data[$descname] . '"></td>
<td id="ServiceDetailColumn"><input type="text" name="' . $qname . '" id="' . $qname .
'" size="4" value="' . $data[$qname] . '"></td>
<td id="ServiceDetailColumn"><input type="text" name="' . $pricename . '" id="' . $pricename .
'" size="7" value="' . $data[$pricename] . '"></td>
<td id="ServiceDetailColumn"><input type="text" name="' . $extname . '" id="' . $extname .
'" size="7" value="' . $data[$extname] . '"></td>

if ($rowcontent != '') {
// Use a submit button to submit to your processor, not a button. Buttons have no inherent action.
// Either add-row or finalize will be present, not both, so use this as a switch in your program
// logic to either return the form or process the order.
$form = '
<form method="post" action="yourscript">
<input type="hidden" name="rownums" value="' . $rownums . '">
<table> ' . $rowcontent . '
<input type="submit" name="add-row" value="+">
<input type="submit" name="finalize" value="Finalize Order">

.. then print $form to the browser.

To do this in Javascript, you'd kinda do the same thing, just loop through the number of rows. You'd have to set "rownum" as a global so each time add row is clicked, it maintains track of the number of rows.

Note also I've dropped the XHTML style syntax, unless you're actually eXtending your html, an HTML doctype more accurately describes your document. It also makes your job easier. Discussion for a different thread . . .


 9:28 pm on Jan 31, 2009 (gmt 0)

This is really good. Just what I was looking for. I will play around with it and see if I can get it to work. I have some basic understanding of php but dynamicly creating the rows is beyond me. I'll work with it and post back here.

Again, thanks so much for your help.


 4:31 pm on Feb 2, 2009 (gmt 0)

Ok, still working on it. Can you please tell me how I would have it remove a row if a check box is ckecked for the row to be deleted?



 5:50 pm on Feb 2, 2009 (gmt 0)

WWTDI . . .


for ($i=1;$i<=$rownums;$i++) {
$deletename = 'Delete' . $i;

if (isset($data[$deletename])) {
// if your data is stored in (my)sql, add command to
// delete the row from the database here



$rowcontent .= '
<td id="ServiceDetailColumn"><input type="checkbox" name="' . $deletename . '" id="' . $deletename .
'" value="1"></td>....

Note that checkbox values are not present in a submitted form unless they are actually checked, so an unchecked box won't be affected by the above conditional.


 6:05 pm on Feb 2, 2009 (gmt 0)

Uhhhhhh..... WOW. You're good! I hope I learn to throw code like that soon.

Thanks. :)


 3:04 am on Feb 14, 2009 (gmt 0)

How would you make the submit script to include the dynamically generated fields? For example, if the user adds another row, how will the submit script now there is a new variable that it needs to get, validate, and process?


 3:39 pm on Feb 14, 2009 (gmt 0)

You do this based on the value of $rownums.

for ($i=1;$i<=$rownums;$i++) {....

so as $rownums increases, so does the number of "fieldsets" that you need to validate.

When the script receives this data*, you use the same iteration scheme to get at the submitted data*:

for ($i=1;$i<=$_POST['rownums'];$i++) {
$partname = 'Part' . $i;
$descname = 'Desc' . $i;
$qname = 'Qty' . $i;
$pricename = 'Price' . $i;
$extname = 'ExtPrice' . $i;
if ((isset($_POST['$qname']) and ($_POST[$qname] > 0)) {
..... (validate the other values for this row set ...
..... compile error response, etc. ....

Another approach I use often, you don't even need to use a $rownum iterator. Look for anything that matches your quantity pattern*. For this to work, I like to use a separator, instead of Qty3 I would use, say, Qty_3*:

foreach ($_POST as $key=>$value) {
if (preg_match("/Qty\_\d+/",$key) {
list($tag,$id) = explode("_",$key);
if ($value > 0) {
$partname = 'Part_' . $id;
$descname = 'Desc_' . $id;
$pricename = 'Price_' . $id;
$extname = 'ExtPrice_' . $id;
.... validate, calculate, etc .....

* You do NOT want to directly use the $_POST variables, they need to be cleansed to avoid injection attacks . . . .


 4:09 pm on Feb 14, 2009 (gmt 0)

I am just learning php. Could you explain what this line does:

$data[$partname] = (isset($data[$partname]))?$data[$partname]:'';

What does the "?" and the ":" do?


 8:24 pm on Feb 14, 2009 (gmt 0)

That is called a terinary (? someone save me) operator or more commonly, a short-circuit evaluation.

Instead of three or four lines,

if (isset($data[$partname])) {
$data[$partname] = $data[$partname];
else { $data[$partname] = ''; }

The short circuit evaluation does it in one line, with "?" and ":" acting as the if/else. If the condition is true, return the FIRST value, otherwise, return the second (after the :.)

$data[$partname] = (isset($data[$partname]))?$data[$partname]:'';

This bit of code may seem like a nonsensical snippet, why set a variable to itself?

It's actually not necessary in most cases and other programming languages, but PHP will give you an "undefined index" warning if you just try to access $data[$partname] and it has not been set. When you get down into the for loop, you see I'm using $data[$partname]. If it has not been set, it will give you a warning, and I hate warnings (see, this is because they could still smack a kid's hand with a ruler when I went to school.) So that part of the code is really to squelch errors, if it's not set I set it to a blank string (or you could use NULL.)

More advanced PHP programmers will probably have a better solution.


 8:34 am on Feb 15, 2009 (gmt 0)

That is called a terinary (? someone save me) operator

operators with one, two or three operands:
unary, binary, ternary...


 3:16 pm on Feb 16, 2009 (gmt 0)

I have another question. If I post back to the same page after validating user input, how would I have it keep the previous added rows and data all ready inputted? Thank you for all your help!


 6:49 pm on Feb 16, 2009 (gmt 0)

Use the rownum variable from post #3, or the split-key method. So you iterate through the rows from 1 to $rownum (or examine each variable looking for the quantity value, if greater than 0 include it,) compile the "key" name, and if it exists, populate the value field:

$partname = 'Part' . $i;
$rowcontent = '
<td id="ServiceDetailColumn"><input type="text" name="' . $partname . '" id="' . $partname .
'" size="15" value="' . $data[$partname] . '"></td>

Remember your previous question - if $data[$partname] has been set, it will have the submitted value.


 1:13 am on Mar 3, 2009 (gmt 0)

I am using this in a different type of form now. The other worked great thanks.

I now need to use something like this to automate giving an id to rows returned from a mysql select statement.

$getrec = mysql_query("SELECT * FROM Tbl WHERE status='holding'");
I then use:
for ($i=1;$i<=$rownums;$i++) { $name = 'use' . $i;
$id = 'use' . $i; } //to add an incremented number in order to use javascript run a total box on my page for selected items
while($data=mysql_fetch_array($getrec)) {
echo '<td>'.$data['date'].'</td>';
echo '<td>'.$data['name'].'</td>';
echo '<td><input type="checkbox" name="'.$name.'" id="'.$id.'" value="'.$data['amount'].'"></td>';
My problem is if there is 3 rows, the names and id's all set to name="use3" id="use3".

How can I make this work right? I'm pretty sure this is caused by calling the $name and $id from the for loop from within the while loop.



 2:08 pm on Mar 3, 2009 (gmt 0)

Sorted out. I was using both for and while when actually I needed to use only the for loop. Kinda makes sense seeing as how they both loop. My mistake. Thanks.

Global Options:
 top home search open messages active posts  

Home / Forums Index / WebmasterWorld / New To Web Development
rss feed

All trademarks and copyrights held by respective owners. Member comments are owned by the poster.
Home ¦ Free Tools ¦ Terms of Service ¦ Privacy Policy ¦ Report Problem ¦ About ¦ Library ¦ Newsletter
WebmasterWorld is a Developer Shed Community owned by Jim Boykin.
© Webmaster World 1996-2014 all rights reserved