Forum Moderators: mack
Please help.
Thanks
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]
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
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">
</table>
</form>
';
}
.. 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 . . .
Add
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
continue;
}
....
and
$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.
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 . . . .
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.
$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.
I now need to use something like this to automate giving an id to rows returned from a mysql select statement.
I.e.
$getrec = mysql_query("SELECT * FROM Tbl WHERE status='holding'");
I then use:
$rownums=mysql_num_rows($getrec);
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>';
}
etc...
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.
Thanks
Kevin