Link to home
Start Free TrialLog in
Avatar of Bruce Gust
Bruce GustFlag for United States of America

asked on

How can I preserve my form data if it fails to validate?

I've got a form that was built by another developer and they did a bang up job!

To facilitate form validation, they've got this in place...

Controller:

// validate fields
		foreach(['campName', 'campPointConv', 'campHierarchy', 'campParticUnits', 'campStartDate', 'campEndDate'] as $requiredField){
			if(!Util::valid($requiredField, $data)){
				$this->addNotice('You are missing required fields', 'error');
				return $this->redirectToRoute('admin_gamification_challenges_edit', ['id'=>$id]);
			}
		}

		if(!empty($data['campAutoSync'])){
			foreach(['campAutoSyncHrId', 'campAutoSyncPoints', 'campAutoSyncUnits'] as $requiredField){
				if(!Util::valid($requiredField, $data)){
					$this->addNotice('You are missing required auto sync fields', 'error');
					return $this->redirectToRoute('admin_gamification_challenges_edit', ['id'=>$id]);
				}
			}

			if(!is_numeric($data['campAutoSyncPoints']) || !is_numeric($data['campAutoSyncUnits'])){
				$this->addNotice('Auto sync points and units must be numbers', 'error');
				return $this->redirectToRoute('admin_gamification_challenges_edit', ['id'=>$id]);
			}
		}

Open in new window


The "Util::valid" method looks like this:

      
public static function valid($key, $vars=[]) {
		// check the variable set
		if (!is_array($vars) || empty($vars) || empty($key)) {
			return false;
		}
		
		// standardize the key into an array of keys
		if (is_string($key)) {
			$key = [$key];
		}
		
		// check each key
		foreach ($key as $k) {
			// fail if the key is an object or array
			if (is_array($k) || is_object($k)) {
				return false;
			}
			
			// check if the key exists
			if (!isset($vars[$k])) {
				return false;
			}
			
			// we can't use empty here because '0' will give a false positive
			if (is_string($vars[$k]) && strlen($vars[$k]) == 0) {
				return false;
			}
		}
		
		// if we made it this far, we're good to go
		return true;
	}

Open in new window


So, it looks like you're ferrying the fields to a method that's looping through them to ensure that there's a value attached to each field.

What's great about this is that in the aftermath of a failed validation, you have something that looks like this:

User generated image
Notice how the fields that have to be populated are in red and the values that were correctly inputted are still in tact.

Now, here comes Bruce...

I added some additional fields at the bottom of the form. They're hidden until the user clicks on a button indicating their desire to input some additional information. It looks like this:

That looks like this:

User generated image
Notice how in the "ending value" field I've got a string?

So, now when this form hits the Controller, that field is going to be evaluated and it will be found to be wanting. Here's the validation code I just referenced with the additional code that I added which is checking for the validity of the values coming from the fields I just added. I've got that in bold:

// validate fields
            foreach(['campName', 'campPointConv', 'campHierarchy', 'campParticUnits', 'campStartDate', 'campEndDate'] as $requiredField){
                  if(!Util::valid($requiredField, $data)){
                        $this->addNotice('You are missing required fields', 'error');
                        return $this->redirectToRoute('admin_gamification_challenges_edit', ['id'=>$id]);
                  }
            }

            if(!empty($data['campAutoSync'])){
                  foreach(['campAutoSyncHrId', 'campAutoSyncPoints', 'campAutoSyncUnits'] as $requiredField){
                        if(!Util::valid($requiredField, $data)){
                              $this->addNotice('You are missing required auto sync fields', 'error');
                              return $this->redirectToRoute('admin_gamification_challenges_edit', ['id'=>$id]);
                        }
                  }

                  if(!is_numeric($data['campAutoSyncPoints']) || !is_numeric($data['campAutoSyncUnits'])){
                        $this->addNotice('Auto sync points and units must be numbers', 'error');
                        return $this->redirectToRoute('admin_gamification_challenges_edit', ['id'=>$id]);
                  }
            }
            
            /*
            here you're looking to make sure that if the "BETWEEN" clause was used for any of the rules, that the values inputted are, in fact, integers
            */

            if(isset($_POST['criteria'])) {
                  foreach ($_POST['criteria'] as $key=>$value )
                  {
                        if($key=='operator' && $value='between') {
                              foreach($_POST['criteria']['between_value_start'] as $thing) {
                                    if(!is_numeric($thing)) {
                                          $this->addNotice('Be sure that your "between" values are integers.', 'error');
                                          return $this->redirectToRoute('admin_gamification_challenges_edit', ['id'=>$id]);
                                    }
                              }
                              foreach($_POST['criteria']['between_value_end'] as $boom) {
                                    if(!is_numeric($boom)) {
                                          $this->addNotice('Be sure that your "between" values are integers.', 'error');
                                          return $this->redirectToRoute('admin_gamification_challenges_edit', ['id'=>$id]);
                                    }
                              }
                        }
                  }
            }


I included the initial "validation" code because when my user submits this form having filled in all of the fields, yet made the mistake of inserting some text into the "ending value" field, they get this:


User generated image
The original validation piece works great in the way it redirects the user back to the form and allows to pick up where they left off.

My addition routes the user back to the form, but all the data that was originally inputted is gone.

What am I missing? How do I preserve the user's correctly inputted information so, should they miss the piece pertaining to the "starting value" and "ending value" fields, they're not having to start all over again?
ASKER CERTIFIED SOLUTION
Avatar of Bruce Gust
Bruce Gust
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial