Member Avatar for skinbug

I have a form and when someone enters incorrect information, the error is displayed.

For the text fields, I have managed to sort it so the user doesn't have to re-type the information as the value is echoed back to them.

But the problem I have is with an array of checkboxes, so when the user checks some of them, if they made an error in the form, then I can't get the checkboxes to remember which ones were checked.

Here is a snippet of the form...

form.php

<input type="text" name="mobile" value="<?php echo $form->value("mobile"); ?>" />

<label><input type="checkbox" name="optional[]" value="chk1" />box 1</label>
<label><input type="checkbox" name="optional[]" value="chk1" />box 2</label>
<label><input type="checkbox" name="optional[]" value="chk1" />box 3</label>

With the 'mobile' text field, the function value() is called which echos back the value entered...so if the user makes a mistake, then they don't need to re-type their mobile number, as it will be stored for them.

process.php

function value($field) {
   if(array_key_exists($field, $this->values)) {
      return htmlspecialchars(stripslashes($this->values[$field]));
   }
   else {
      return "";
   }
}

I have tried to do the same thing with the checkboxes, but can't figure it out...this is what I have so far...

<input type="checkbox" name="optional[]" value="chk1" <?php if($form->value("mandatory") != ""){ echo "checked == 'checked'"; } ?> />

The problem with this, is if someone checks one checkbox but has an error somewhere else in the form, then the form is sent back to them with all three checkboxes being checked! as they have the same name.

I'm sure this must be a fairly common senario, but can't find the answer on Google anywhere.

I have tried so many variations of this code and haven't managed to get it working...can help me!!!

How are you bringing the values back? get, post, session, cookie?

Member Avatar for skinbug

If you mean for the form, it has an action="preocess.php" method="post"

Is that what you mean?

If you mean for the form, it has an action="preocess.php" method="post"

Is that what you mean?

Not necessarily, sure you post the form to the server but how are you sending the incorrect data back to the page?

for example, I generally use a session. So I post the data to the server and if it doesn't validate, I assigned the posted values to a session array to repopulate the form back to the user.

Member Avatar for skinbug

I've shown this in the script...

for a text field...

value="<?php echo $form->value("mobile"); ?>"

That points to a function in process.php called value() (code is shown in original post for this function) and the name of the field is in the brackets.

Basically, it echos back what they type.

The problem for the array of checkboxes is that this method relies on having a unique name, so when you check one box, sunmit the form with errors, the script checks any box with the name of optional which is all of them?!?

I have tried things like optional[1], optional[2], etc....didn't work :(

Member Avatar for skinbug

if you can point me to any tutorials on this then I can go from there, but I can't find any on google...I don't know what to type.

I type things like 'save form data php'
that comes up with how to store in database etc

or

store form value...gets the same hits

return form value to user...no luck!!

So as you can see, I can't get started because I can't find any guides, even though this must be a common problem

Member Avatar for langsor

Hi,

I've been following along and trying to understand what you're trying to do here -- mostly I'm confused.

Is there a compulsory reason to give the check boxes the same name? Because I don't think that is a common approach at all. Radio buttons get the same name because they are one value in a set of many, but check boxes are one value in a set of one and using the same name makes very little sense to me. Your solution would be cake if you had different names for each button.

Also, in your example, all boxes have the same value too ??? Maybe I'm being clueless here and not getting the point ... but same name, same value ??? Even if your values are different, and the above is just example code, then you need to store the value like R0bb0b suggested and do a test against each html <input> string to see what value it holds and then mark it as checked, or not, before writing the page back to the browser.

Sorry if I'm being clueless here, just trying to help, really

Member Avatar for langsor

Something like this might be what you're looking for ?

<?php

$form = <<<ENDFORM
<form method="post" action="untitled.php">
  <label for="opt1"><input id="opt1" type="checkbox" name="optional[]" value="1" />One</label>
  <label for="opt2"><input id="opt2" type="checkbox" name="optional[]" value="2" />Two</label>
  <label for="opt3"><input id="opt3" type="checkbox" name="optional[]" value="3" />Three</label>
  <input type="submit" />
</form>

ENDFORM;

$doc = new DOMDocument();
$doc->loadHTML( $form );
$ins = $doc->getElementsByTagName('input');
$frm = $doc->getElementsByTagName('form')->item(0);

if ( !empty( $_POST ) ) {
  foreach ( $ins as $input  ) {
    foreach ( $_POST['optional'] as $value ) {
      if ( $input->getAttribute('value') == $value ) {
        $input->setAttribute( 'checked', 'checked' );
      }
    }
  }
}

?>
<html>
<head>
</head>
<body>
<?php print $doc->saveXML($frm); ?>
</body>
</html>

Hope it helps :-)

Something like this might be what you're looking for ?

<?php

$form = <<<ENDFORM
<form method="post" action="untitled.php">
  <label for="opt1"><input id="opt1" type="checkbox" name="optional[]" value="1" />One</label>
  <label for="opt2"><input id="opt2" type="checkbox" name="optional[]" value="2" />Two</label>
  <label for="opt3"><input id="opt3" type="checkbox" name="optional[]" value="3" />Three</label>
  <input type="submit" />
</form>

ENDFORM;

$doc = new DOMDocument();
$doc->loadHTML( $form );
$ins = $doc->getElementsByTagName('input');
$frm = $doc->getElementsByTagName('form')->item(0);

if ( !empty( $_POST ) ) {
  foreach ( $ins as $input  ) {
    foreach ( $_POST['optional'] as $value ) {
      if ( $input->getAttribute('value') == $value ) {
        $input->setAttribute( 'checked', 'checked' );
      }
    }
  }
}

?>
<html>
<head>
</head>
<body>
<?php print $doc->saveXML($frm); ?>
</body>
</html>

Hope it helps :-)

Very interesting, I have never used the DOM in php. I will have to give that a try.

Member Avatar for langsor

It beats RegEx nine times out of ten for ease of use, but does have a little learning curve to it.

I started out trying the above with RegEx, but got tired of beating my head against my laptop so went to DOM methods instead. :-)

By the way, I have never gotten the PHP to handle ->getElementById() successfully, so have to sift through the elements and search for the id with ->getAttribute('id') == 'my_id' approach.

Ciao

Member Avatar for skinbug

cheers for the response guys...you lot obviously have much more knowledge/experience then me!!

To the one talking about the same values for each checkbox, yes that is a typo...I have them as unique values in the script....copy/paste error.
The same name is used as it puts them in an array.

To the one talking about how the data is returned, then I belive it is in a session...i think it goes like this...

1. someone enters incorrect data, submits form. (reg.php)
2. form is processed and values are posted. (process.php)
3. values get validated, if error is found, 1 is returned. (session.php)
4. form class is storing all the values in an array stored in $field (form.php)
5. data is sent back to form, including error messages (reg.php)
6. values and error messages are echoed

My friend suggested that to see if any data has been entered into checkbox, ie one is checked, to see if anything exists then I would need to look at extrecting information from nested array. As the form data is stored in array $field, then this will also contain the chkbox array, ergo nested array...I'm going to look further into this today, and also at the example someone posted earlier...thanks for response, will report back later.

ok, this is what I normally do.

<?
$chkboxcolorarray = array();
$chkboxcolorarray[] = "red";
$chkboxcolorarray[] = "green";
$chkboxcolorarray[] = "blue";
$chkboxcolorarray[] = "black";

$chkboxcolorhtml = "";
foreach($chkboxcolorarray as $value)
{
	$checked = "";
	if(in_array($value, $_SESSION['form']['chkColors']))
	{
		$checked = ' checked="checked"';
	}
	?>
	<input type="checkbox" id="chkColors" name="chkColors[]"<? echo $checked; ?> value="<? echo $value; ?>" />
	<?
}
?>

Then on the page that your form submits to:
1. clear the session at the top by using:

$_SESSION['form'] = NULL;
unset($_SESSION['form']);

2. if the input from the form is invalid I do this:
$_SESSION = $_POST;

But it looks like you are using a class so if that is the way you want to go you will need to post the code from your class.

Member Avatar for skinbug

Robbob, I am interested in trying to intergrate your solution with my script. Your right, the code I am working with is spit up into classes and it goes like this...

reg.php

require_once("include/session.php");

<form action="process.php" method="post">
<input type="text" name="user" value="<?php echo $form->value("user"); ?>" /><?php echo $form->error("user"); ?>

<label><input type="checkbox" name="optional[]" value="box1" />Box 1</lable>
<label><input type="checkbox" name="optional[]" value="box2" />Box 2</lable>
<label><input type="checkbox" name="optional[]" value="box3" />Box 3</lable>

<input type="hidden" name="subjoin" value="1" /><input id="submit" type="submit" value="Submit" />
</form>

process.php

include("include/session.php");

class Process {
   function Process() {
      global $session;
      if(isset($_POST['subjoin'])) { // User submits registration form
         $this->procRegister();
      }
   }

   // Processes submitted reg form...if errors, user is re-directed to correct them
   function procRegister() {
      global $session, $form;
      
      // registration attempt
      if(isset($_POST['optional'])) {
         $retval = $session->register(implode(",",$_POST['optional']));
      }
      else {
         $retval = $session->register($_POST['optional']);
      }

      // registration successful
      if($retval == 0) {
         $_SESSION['reguname'] = $_POST['user'];
         $_SESSION['regsuccess'] = true;
         header("Location: ".$session->referrer);
      }
      else if($retval == 1) { // errors found with form
         $_SESSION['value_array'] = $_POST
         $_SESSION['error_array'] = $form->getErrorArray();
         header("Location: ".$session->referrer);
      }
      else if($retval == 2) { // registration attempt failed
         $_SESSION['reguname'] = $_POST['user'];
         $_SESSION['regsuccess'] = false;
         header("Location: ".$session->referrer);
      }
   }
};

$process = new Process;

session.php

include("database.php");
include("form.php");

class Session {

   var $username;
   var $time;
   var $referrer;
   // additional vars declared

   function Session() {
      $this->time = time();
      $this->startSession();
   }

   // initialize session object...determines if already logged in
   function startSession() {
      global $database;
      session_start();

      // further code here...
   }

   // called when form submitted...determines if any errors, records them and returns 1.
   function register($subuser, $suboptional) {
      global $database, $form;

      // Username error checking
      $field = "user"; // field name for username
      if(!subuser || strlen($subuser = trim($subuser)) == 0) { // blank field
         $form->setError($field, "* Username not entered.");
      }
      else {
         $subuser = stripslashes($subuser);
         // Further error checking for length of name etc...
      }

      // Checkbox error checking
      $field = "optional"; // field name for checkboxes
      if($suboptional && sizeof($suboptional) > 1) { // a checkbox has been checked
         $suboptional = stripslashes($suboptional);
      }
      // Further validation is required...not yet done

      // Errors with form exist
      if($form->num_errors > 0) {
         return 1;
      }
      else {
         if($database->addNewUser($subuser, $suboptional)) {
            return 0; // Success
         }
         else {
            return 2; // Reg attempt failed
         }
      }
   }
};

$session = new Session;
$form = new Form;

form.php

class Form {
   var $values = array(); // holds submitted form field values
   var $errors = array(); // holds submitted form error messages
   var $num_errors; // number of errors in submitted form

   function Form() {
      
      // get form value + error arrays, used when error with submitted form
      if(isset($_SESSION['value_array']) && isset($_SESSION['error_array'])) {
         $this->values = $_SESSION['value_array'];
         $this->errors = $_SESSION['error_array'];
         $this->num_errors = count($this->errors);
			
         unset($_SESSION['value_array']);
         unset($_SESSION['error_array']);
      }
      else {
         $this->num_errors = 0;
      }
   }

   function setValue($field, $value) { // records value typed into form field
      $this->values[$field] = $value;
   }

   function setError($field, $errmsg) { // records new form error, field name and message
      $this->errors[$field] = $errmsg;
      $this->num_errors = count($this->errors);
   }

   function value($field) { // returns value to given field, or empty string
      if(array_key_exists($field,$this->values)) {
         return htmlspecialchars(stripslashes($this->values[$field]));
      }
      else {
         return "";
      }
   }

   function error($field) { // returns error message to given field, or empty string
      if(array_key_exists($field,$this->errors)) {
         return "<p class='errorMsg'>".$this->errors[$field]."</p>";
      }
      else {
         return "";
      }
   }

   function getErrorArray() {
      return $this->errors;
   }
};

Phew! that's it

There are other parts to the script which I have not shown such as other registration fields, further validation, and database.php, but the form has not yet reached the database, since we are assuming errors with form have been made.

You can assume any errors here are typos, functionality is tested and working with other form fields.

So going back to your example that you showed me earlier (the checkboxcolour array), could you advise me on how I could intergrate it to this script I have here, which is split into objects/classes?

Your time is appreciated on so many levels!!

theoretically, this should work, let me know if you get any unexpected outcomes.

<?
require_once("include/session.php");
?>

<form action="process.php" method="post">
<input type="text" name="user" value="<?php echo $form->value("user"); ?>" /><?php echo $form->error("user"); ?>
<?
$chkboxoptionalarray = array();
$chkboxoptionalarray[] = "box 1";
$chkboxoptionalarray[] = "box 2";
$chkboxoptionalarray[] = "box 3";

$chkboxoptionalhtml = "";

$chkselValues = $form->value("optional");
foreach($chkboxoptionalarray as $value)
{
	$checked = "";
	
	if(in_array(str_replace(" ", "", $value), $chkselValues))
	{
		$checked = ' checked="checked"';
	}
	?>
	<label><input type="checkbox" id="optional" name="optional[]"<? echo $checked; ?> value="<? echo str_replace(" ", "", $value); ?>" /><? echo ucwords($value); ?></lable>
	<?
}
?>

<input type="hidden" name="subjoin" value="1" /><input id="submit" type="submit" value="Submit" />
</form>
Member Avatar for skinbug

from this i get warning...

warning: in_array()[function.in-array]: wrong datatype for second argument in c:\wamp\www\...

then it displays a checkbox with the label of box 1

This is for all 3 chkboxes.

I have been getting this sort of message with many of the attempts i have made with this. I can't believe that checkboxes can be so difficult, or what I am trying to do with them is so wild.

I have half a mind to stuff the array and create a field for each and every box and send back errors individually...i have this working for an individual checkbox in exaclty the same way as I do for a text field...it is the array that complicates things so much. It is a crude method, but works...

Ok listen, no need to sweat over this...it's not worth it...if you do find a solution, then let me know, as the array method seems far more elegant,

Thanks again, rob.

from this i get warning...

warning: in_array()[function.in-array]: wrong datatype for second argument in c:\wamp\www\...

then it displays a checkbox with the label of box 1

This is for all 3 chkboxes.

I have been getting this sort of message with many of the attempts i have made with this. I can't believe that checkboxes can be so difficult, or what I am trying to do with them is so wild.

I have half a mind to stuff the array and create a field for each and every box and send back errors individually...i have this working for an individual checkbox in exaclty the same way as I do for a text field...it is the array that complicates things so much. It is a crude method, but works...

Ok listen, no need to sweat over this...it's not worth it...if you do find a solution, then let me know, as the array method seems far more elegant,

Thanks again, rob.

Ok, well I'll play with it in a little bit.

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.