Auto-fill Form Fields from User Input. Best Practice?

Not for 'how-to' coding questions but PHP theory instead, this forum is here for those of us who wish to learn about design aspects of programming with PHP.

Moderator: General Moderators

Post Reply
User avatar
hawleyjr
BeerMod
Posts: 2170
Joined: Tue Jan 13, 2004 4:58 pm
Location: Jax FL & Spokane WA USA

Auto-fill Form Fields from User Input. Best Practice?

Post by hawleyjr »

I am curious to see how other people auto-fill form fields from user input. Say you have a form that has multiple drop down boxes, radio fields, text boxes, etc. The following page validates the (user inputted) form data. If there is an error in the form data I redirect back to the form pre-fill all form fields with the previously submitted values and inform the user of the error.

My question:

How do you prefill the form fields with the user submitted data?

I typically store the $_POST var in a session variable with an error flag:

Code: Select all

<?php
//PROCESS PAGE
//$_POST
Array
(

    [fld_18_1] => hawleyjr
    [fld_19_1] => FL
    [fld_20_1] => 8
    [fld_21_1] => 555
    [fld_22_1] => 
    [fld_25_1] => 
    [fld_26_1] => AAA Insurance Co.
    [fld_27_1] => 1
    [fld_28_1] => 1
    [fld_29_1] => No
    [fld_30_1] => 
    [fld_31_1] => No Military Experience
    [fld_32_1] => Chef
    [fld_33_1] => McDonalds
    [fld_34_1] => 5
    [fld_35_1] => MY G
    [fld_36_1] => No
    [fld_43_1] => 5 YRS COMMENTS
    [fld_69] => 
    [Submit] => Submit
)

//on error
$_SESSION['USER_DATA'] = $_POST;
//redirect back to form page
?>
Text boxes are the easiest to autofill:

Code: Select all

<?php
//FORM PAGE
$a_user_data = $_SESSION['USER_DATA'];
?>
<input type="text" name="fld_18_1" value="<?php echo a_user_data['fld_18_1'];?>">
When it comes to listboxes there are a few options:

For instance, if you have a listbox of states:

Code: Select all

&lt;select name="fld_19_1"&gt;
	&lt;option value="AL"&gt;Alabama&lt;/OPTION&gt;
	&lt;option value="AK"&gt;Alaska&lt;/OPTION&gt;
	&lt;option value="AZ"&gt;Arizona&lt;/OPTION&gt;
	&lt;option value="AR"&gt;Arkansas&lt;/OPTION&gt;
	&lt;option value="CA"&gt;California&lt;/OPTION&gt;
	&lt;option value="CO"&gt;Colorado&lt;/OPTION&gt;
	&lt;option value="CT"&gt;Connecticut&lt;/OPTION&gt;
	&lt;option value="DE"&gt;Delaware&lt;/OPTION&gt;
	&lt;option value="DC"&gt;District Of Columbia&lt;/OPTION&gt;
	&lt;option value="FL"&gt;Florida&lt;/OPTION&gt;
	&lt;option value="GA"&gt;Georgia&lt;/OPTION&gt;
	&lt;option value="HI"&gt;Hawaii&lt;/OPTION&gt;
	...
	&lt;/select&gt;
I have used three different methods to auto fill a list box so the selected values are displayed.
1. Insert if Statement into each Option.
2. Call function to loop through array of values and labels.
3. Use JavaScript to setIndex onLoad.

1. Insert if statement in each <option>:

Code: Select all

<?php
		$s = ' selected';
?>	
		<option value="AL"<?php if($a_user_data[fld_19_1]=='AL')echo $s;?>>Alabama</OPTION>
		<option value="AK"<?php if($a_user_data[fld_19_1]=='AK')echo $s;?>>Alaska</OPTION>
		<option value="AZ"<?php if($a_user_data[fld_19_1]=='AZ')echo $s;?>>Arizona</OPTION>
		<option value="AR"<?php if($a_user_data[fld_19_1]=='AR')echo $s;?>>Arkansas</OPTION>
		<option value="CA"<?php if($a_user_data[fld_19_1]=='CA')echo $s;?>>California</OPTION>
		<option value="CO"<?php if($a_user_data[fld_19_1]=='CO')echo $s;?>>Colorado</OPTION>
		<option value="CT"<?php if($a_user_data[fld_19_1]=='CT')echo $s;?>>Connecticut</OPTION>
		<option value="DE"<?php if($a_user_data[fld_19_1]=='DE')echo $s;?>>Delaware</OPTION>
		<option value="DC"<?php if($a_user_data[fld_19_1]=='DC')echo $s;?>>District Of Columbia</OPTION>
		<option value="FL"<?php if($a_user_data[fld_19_1]=='FL')echo $s;?>>Florida</OPTION>
		<option value="GA"<?php if($a_user_data[fld_19_1]=='GA')echo $s;?>>Georgia</OPTION>
		<option value="HI"<?php if($a_user_data[fld_19_1]=='HI')echo $s;?>>Hawaii</OPTION>
OK, it’s easy to say how ugly and cumbersome this is. It works for small list boxes. In my opinion; poor programming practice.

2. Call a function that will loop through an array and echo out the list box:

Code: Select all

<?php
		$a_st_abrev = array('AL','AK','AZ','AR','CA','CO','CT','DE','DC','FL','GA','HI'....);
		$a_st_long_name = array('Alabama','Alaska','Arizona','Arkansas','California','Colorado',
					'Connecticut','Delaware','District Of Columbia','Florida','Georgia','Hawaii'....);
		
		$selected_value = $a_user_data['fld_19_1'];
	?>	
		<select name="fld_19_1">
			<?php 
			//FUNCTION IS LOCATED AT BOTTOM OF POST
			echo getSelectBoxOptions($a_st_long_name,$a_st_abrev,$selected_value,FALSE);
			?>
		</select>
Probably my most favorable option. My only concern is page load time. If I have a couple dozen list boxes that are over 50 elements each, how much will this drag on the page load?

3. Have JavaScript set the selected Index onLoad:

Code: Select all

<SCRIPT language="javascript">
			function setState(){
		
				fld_st = eval("document.form1.fld_19_1");
				fld_cur_len = fld_st.length;
				for(x=0;x<fld_cur_len;x++){
					if(fld_st[x].value == "<?php echo $a_user_data['fld_19_1'];?>"){
						fld_st.selectedIndex = x;
						break;
					}
				}
			}
		</SCRIPT>
		<BODY ONLOAD="setState();">
Probably my least favorite option just because it’s JavaScript and I'm now relying on my user to have the correct JavaScript browser settings.

For Radio Buttons and Check Boxes I have found the first option to be the most useful.

I am curious to find out what you do in the same circumstance is there another method I overlooked?


Code: Select all

<?php
//FUNCTION USED IN OPTION 2:
/*  ECHO OUT THE HTML NEEDED FOR A HTML LIST BOX 

	$a_displayValues	LABEL OF EACH OPTION
	$a_optionValues		OPTION VALUES
	$selected_option_value	SELECTED INDEX
	IF $a_optionValues IS NULL USE DISPLAYVALUES ARRAY KEY
	IF $echoHTML IS TRUE ECHO HTML ELSE RETURN HTML
*/

function printSelectBoxOptions($a_displayValues, $a_optionValues, $selected_option_value,$echoHTML){
	
	$html = '';
	
	$arrayCount = 0;
	foreach ($a_displayValues as $x => $v) {
		
		if($a_optionValues==null){
			$a_optionValues = array_keys($a_displayValues);
		}
	
		if($selected_option_value==$a_optionValues[$arrayCount])
			$sel = ' selected';
		else
			$sel = '';
			
	  $html.= '<option value="'.$a_optionValues[$arrayCount].'"'.$sel.'>'.$a_displayValues[$x].'</option>'."\r";
	  $arrayCount++;

	}
	if($echoHTML){
		echo $html;
		return TRUE;
	}else{
		return $html;
	}

}
?>
apple
Forum Newbie
Posts: 21
Joined: Wed Mar 03, 2004 12:50 am
Contact:

I usually put the Data in MySql

Post by apple »

For example:

I strored the options on MySql, I just add another table on the recent database I have.

Code: Select all

<?php 

echo '<select prefix_id="$prefix">';	
	  // Display the type_id:
	$query_result = mysql_query("SELECT * FROM prefix ORDER BY id");
	 while ($row = mysql_fetch_array($query_result, MYSQL_NUM)) {
echo "<option value="$row[0]">$row[1]</option>\n";
	};
echo '</select>';
	// Tidy up (not required):
	mysql_free_result($query_result);
	mysql_close();

?>
So If I want to add additional options I dont have to rewrite the Script, I just simple add the options on MySql
User avatar
hawleyjr
BeerMod
Posts: 2170
Joined: Tue Jan 13, 2004 4:58 pm
Location: Jax FL & Spokane WA USA

Post by hawleyjr »

Which is fine for populating select fields. (I don't recommend imbedding queries in HTML) But how do you auto index a select box based off of user input when the page loads?
dave420
Forum Contributor
Posts: 106
Joined: Tue Feb 17, 2004 8:03 am

Post by dave420 »

I usually make an associative array tying the field names (as indices) to an array describing conditions the field has to make to be valid. These include regular expression matches, to function callbacks. It's trivial to make a function that checks these fields against, say, $_POST data. The function can even update the array, to note which fields are incorrect. If any are found to be incorrect, passing the modified array back to my templating engine allows the template to display error text next to the field (using conditions, based on the errors noted in the array).

I was fed up of having to code the problem you describe for each user-input form, and decided to make some intelligent code to do it for me. Now, the whole process can be done in a few lines of code, and is totally re-usable.
User avatar
hawleyjr
BeerMod
Posts: 2170
Joined: Tue Jan 13, 2004 4:58 pm
Location: Jax FL & Spokane WA USA

Post by hawleyjr »

Dave interesting concept. I'd love to see any code examples you have.

-James
jason
Site Admin
Posts: 1767
Joined: Thu Apr 18, 2002 3:14 pm
Location: Montreal, CA
Contact:

Post by jason »

One of these days I will format, and post my validation stuff to the wiki. It's good stuff, and makes my life easier.

The key to validation is to go beyond regular expressions. The difference between reporting an error and fixing it for the user is immense.

Take a simple thing such as a username. If the user enters a username that's already taken, the system should provide the user with other choices of usernames that are not already taken.

Or a phone number. For example, in England, whose country code is 44, someone could enter a phone number like so:

Code: Select all

44 (020) 33445555
Now, let's say you only want numbers for the phone number. This means that the above phone number is incorrect. It's also incorrect because it doesn't have a 011 in front of it (something North American's need to dial outside North America), and there is a 0 in the front of city code (020).

However, rather than report this as an error to the user and explain to him all those rules, you can clean it up for him.

Remove the ( and ), remove the leading 0 from 020, place 011 at the beginning, and remove the spaces. It's all something you can easily do from coding using [php_man]str_replace[/php_man] and other hand functions.

Then you will have a correct phone number without having the problem of annoying the user with an error. The user, after all, entered a correct phone number.
User avatar
hawleyjr
BeerMod
Posts: 2170
Joined: Tue Jan 13, 2004 4:58 pm
Location: Jax FL & Spokane WA USA

Post by hawleyjr »

I haven't dealt with international phone numbers but I do the same thing for ss# and dates

555-22-5555 same as 555225555
4.22.2004 same as 04.22.2004
dave420
Forum Contributor
Posts: 106
Joined: Tue Feb 17, 2004 8:03 am

Post by dave420 »

jason - that's exactly it. You assign callbacks to correct data where you can. Automating the process means you always have a rigid structure in place to ensure your form data is validated. all good stuff :)
McGruff
DevNet Master
Posts: 2893
Joined: Thu Jan 30, 2003 8:26 pm
Location: Glasgow, Scotland

Post by McGruff »

hawleyjr wrote:Dave interesting concept. I'd love to see any code examples you have.

-James
If dave will excuse me butting in, I think I'm using a similar system - maybe this will give you some ideas.

With a file naming convention, meta data can be dynamically included based on (for example) the module name and the module command (passed via GET).

The array below specifies two tests to be carried out on an 'id' key. 'req_exists' = true means the key must exist and 'req_val' = true means it is required to validate.

A class, or rather bunch of classes, can iterate through the lists of tests for each key described in the meta data array.

Code: Select all

<?php

$meta = array();

$meta['id']['req_exists'] = true;
$meta['id']['req_val'] = true;
$meta['id']['tests'][0]['class'] = 'IsNumeric';
$meta['id']['tests'][0]['script'] = 'lib/validation/isnumeric.php';
$meta['id']['tests'][0]['args'] = '';
$meta['id']['tests'][0]['message'] = 'Aaaargh!'; // optional custom message which overides the default in the IsNumeric class

$meta['id']['tests'][1]['class'] = 'InRange';
$meta['id']['tests'][1]['script'] = 'lib/validation/inrange.php';
$meta['id']['tests'][1]['args'] = array('min'=>4, 'max'=>50);

return $meta;

?>
In between unavoidable bouts of employment, I'm trying to finish off a "Firewall" class which acts as a proxy for GPC input.
Post Reply