Welcome Guest, Not a member yet? Register   Sign In
Form validation with redirect
#1

Although this subject has come up a munber of times, tantalisingly the posts do not quite address my problem.

Assuming form validation fails, the 'send' function needs to reload the form page with the validation error messages. However, because the form is some way down the page, I want to add '#anchor' to the url and autoscroll down to the form. So the only way to do that is to use the url helper redirect() function. That gets me back to the form OK but now the validation messages are not being passed.

My question is how can achieve both these requirements: passing validation data and also autoscrolling down to the form?

I wonder whether in some way I can add an array of validation messages to flashdata and pass it that way?

I can't believe this is not a typical problem. Any ideas?
Reply
#2

I assume you are posting to the same page where the form is loaded and validated. In that case you could add the #anchor to the post URL. Using flashdata would require more conditionals
Reply
#3

(10-26-2015, 05:34 AM)Martin7483 Wrote: I assume you are posting to the same page where the form is loaded and validated. In that case you could add the #anchor to the post URL. Using flashdata would require more conditionals

The form is on its own page but the validation is done, as normal, in the controller in what I have called the 'send' function. Having set the validation rules I do:

Code:
if($this->form_validation->run() == false)

        {
            redirect('site/home#anchor');
        }
and that takes me back to the page and autoscrolls to the anchor (ie the form) but the validation errors are not passed. If instead I do


Code:
if($this->form_validation->run() == false)
{
$this->home;
}
I get to the page and validation errors are passed but I land at the top of the page instead of scrolling down to the form. If I do:

Code:
if($this->form_validation->run() == false)
{
$this->home#anchor');
}

There is a 'not found' error because there is no page with a url of .../home#anchor.php
So I'm stuck!
Reply
#4

Your home and send method are in the same controller. Add your validation check to your home method. When valid you can then pass it to your send method for processing. Doing this your post url can be /home#anchor
Reply
#5

(10-26-2015, 07:44 AM)Martin7483 Wrote: Your home and send method are in the same controller. Add your validation check to your home method. When valid you can then pass it to your send method for processing. Doing this your post url can be /home#anchor

Thanks so much for you help. However I'm afraid you've lost me with the last advice. Clicking send in the form page currently directs me to the send method in the controller. Are you suggesting that instead it should go to the home method where the validation rules are then set and then conditionally either the home page is reloaded with validation errors or it is passed to the send method?

My home method is currently this:

Code:
        $this->data['body_id'] = 'home';
        $this->data['main'] = 'pages/home_view';    
        $this->load->view('templates/template_main_view', $this->data);
I have already tried changing it to:

Code:
        $this->data['body_id'] = 'home';
        $this->data['main'] = 'pages/home_view#anchor';    
        $this->load->view('templates/template_main_view', $this->data);
but I get the not found error because it's trying to reach a page .../home#anchor.php which obviously doesn't eist
Reply
#6

Hi,

I would like to share my opinion.

From the thread, I found this block of statement.
Quote:$this->data['body_id'] = 'home';
$this->data['main'] = 'pages/home_view#anchor';    
$this->load->view('templates/template_main_view', $this->data);
The second line causes the error you had. (trying to reach a page .../home#anchor.php which obviously doesn't eist)

I supposed you had a code in templates/template_main_view.php like this
PHP Code:
<!--With some html elements -->
<?
php $this->load->view($main); ?>
$main is not a link it is most likely a string that is referring to a specific file under the View folder. I suggest you can remove the #anchor from your controller method home to remove the error.

Now what I understood, you want to autoscroll to the specific part of your html document and show the errors. 
Quote:To retain your goal to have autoscroll, redirect method will help you. But consequently, you will lose the validation messages since, the page is reloaded.
You can use flashdata for this matter. Storing all the validation messages to flashdata and printing it to your view will solve the problem.

I have searched from the internet and found some helpful links here. 
https://www.codeigniter.com/user_guide/l...#flashdata
http://stackoverflow.com/questions/12353...flash-data

Please refer to my example,

In the Controller,
PHP Code:
public function home($any '') {
 
   $this->session->set_flashdata('error''')
 
   $this->load->view('samples/test');
}

public function 
send() {
 
   $this->load->library('form_validation');

 
   if($this->form_validation->run()) {
 
       //do your stuff here
 
   } else {
 
       $std = new stdClass(); // just and example (to show that flash_data can hold complex values)
 
       $std->error 'some error'
 
       
        
// you can get the validation messages from form_validation
 
       // $std = validation_errors(); //just uncomment this part, this should work
 
       
        $this
->session->set_flashdata('error'$std);
 
   }

 
   redirect(base_url('index.php/sample/home#anchor'));


In View,
Code:
// form above

// The viewport should autoscroll in this part if url has #anchor (any id)
<section id="anchor">
  <?php echo $this->session->flashdata('error')->error; ?>
</section>

I hope I help you somehow. I will make some research on this matter and revise this post if ever I find new approach..

Thank you. Have a nice day.

- joseph.dicdican  Big Grin
Joseph K. Dicdican
Softshore Global Solutions Inc. | Junior Web Developer Intern
Passerelles numériques Philippines | Scholar
[email protected] 
Reply
#7

Redirecting is never the solution ... every single time I see a thread with a title similar to this one, I know the OP is doing something wrong.

You can use JavaScript to scroll down in case of an error.
Reply
#8

(This post was last modified: 10-27-2015, 10:41 AM by joseph.dicdican. Edit Reason: added images for example )

(10-27-2015, 03:42 AM)Narf Wrote: Redirecting is never the solution ... every single time I see a thread with a title similar to this one, I know the OP is doing something wrong.

You can use JavaScript to scroll down in case of an error.

I agree to what Narf said here. I just knew flashdata just this day not deeply. I still don't know yet when to use this feature. It is not a best solution to redirect when implementing notifications/error message reporting.

Regarding the main topic, I would just like to share my usual way on implementing error messages. (e.g. notifications)

First I always have a private property called $data (array)in my controller. (e.g. private $data = array())
Then, I some codes like below,
 Controller part,
PHP Code:
// intended for errors, titles etc.
private $data = array();

public function 
dummy() 
{
 
   $this->send();

 
   $this->load->view('test/test'$this->data);
}

private function 
send() 
{
 
   $this->data['hasError'] = true;
 
   $this->load->library('form_validation');

 
   $this->form_validation->set_rules('username''Username''trim|required');

 
   if($this->form_validation->run()) {
 
       $this->data['hasError'] = false;
 
       //do some stuff here
 
   }


View part,
Code:
<?php if($hasError) { // check if has error ?>
   <section id="errors">
       <?php echo validation_errors(); ?>
   </section>
<?php } //close if has error ?>

For the javascript part to have an autoscroll feature, but I suggest to make use of jquery library to have convenient javascript codings.
Code:
<script type="text/javascript">
   window.onload = function() {
       var errors = document.getElementById('errors');

       //auto scroll only if section#errors exist
       if(errors) { //this also do I assumed, errors.length > 0
           errors.scrollIntoView(true);
       }
   }
</script>
I have tested the auto scroll by adding lots of <br /> element before the section with id errors. It worked fine.
You can also refer to this link to see more of auto scroll using javascript. 

Please see attachment for my local example.
               

I hope this can help. Thank you.

-joseph.dicdican  Smile
Joseph K. Dicdican
Softshore Global Solutions Inc. | Junior Web Developer Intern
Passerelles numériques Philippines | Scholar
[email protected] 
Reply
#9

(This post was last modified: 10-27-2015, 12:21 PM by Martin7483.)

What is the url to your form? I'm assuming it is /home and your post url is /home/send. If this is the case then you are defining you rules in the send method and you then validate your posted form.

Define your rules in the home method and do your validation in your home method. Your post URL would then be /home#anchor instead of /home/send. If the validation fails, the view with your form and errors is loaded and the #anchor wil take you to your form. No need for JavaScript.

If the form passed validation you could redirect to your send method and save the post dataset in a flashdata for processing in your send method.

PHP Code:
class Home extends CI_Controller {
 
   
    public 
function home() {
 
       if ($this->form_validation->run() == FALSE) {
 
           $data['post_url'] = '/home#anchor';
 
           $this->load->view('yourform'$data);
 
       } else {
 
           $this->session->set_flashdata('yourform'$this->input->post());
 
           redirect(base_url('home/send'));
 
       }
 
   }
 
   
    public 
function send() {
 
       // If your flashdata item is not set NULL is returned
        
$post $this->session->flashdata('yourform');
        if( ! 
is_null($post) ) {
 
           // Do what you want to do with your post dataset
 
       } else {
 
           // The form has already been processed
 
           $this->load->view('form_already_processed');
 
       }
 
   }


Maybe my example can help you on your way. In my example the problem of double form posting is also solved
Reply
#10

I have a view which looks something like this:

PHP Code:
<h1>Test Page</h1>
<
p>Lorem ipsum etc.</p>
<
h2 id='my_form'>Form</h2>
<?
php if (! empty($errorMessage)) : ?>
<div class='alert alert-error'>
    <h4 class='alert-heading'><?php echo lang('test_model_error_heading'); ?></h4>
    <?php echo $errorMessage?>
</div>
<?php
endif;
if (
validation_errors()) :
?>
<div class='alert alert-error'>
    <h4 class='alert-heading'><?php echo lang('test_validation_errors_heading'); ?></h4>
    <?php echo validation_errors(); ?>
</div>
<?php 
endif;
echo 
form_open(site_url('myform/home') . '#my_form''class="form-class"'); 
?>
    <fieldset>
         <?php 
        
// form fields here
 
       ?>
    </fieldset>
    <?php if ($canEdit) : ?>
    <fieldset class='form-actions'>
        <input type='submit' name='submit' value="<?php echo lang('test_edit_button'); ?>" class='edit-button' />
    </fieldset>
    <?php endif; ?>
<?php 
echo form_close(); ?>

Note that '#my_form' is appended to the URL in form_open(), which causes the page to return to the form if I don't redirect in the controller, without the need for JavaScript. Also note that validation_errors() returns an empty string if there are no validation errors, so I only need to set additional variables for error handling if I'm dealing with error messages generated by another part of the system, like my model (if validation didn't catch something).


Then the controller does something like this:

PHP Code:
class Myform extends CI_Controller
{
 
   // ...

 
   public function home()
 
   {
 
       $data = array();

 
       // $this->canEdit is a stand-in for checking whether the user 
 
       // is authorized to submit this form.
 
       if ($this->input->post('submit') && $this->canEdit) {
 
           $result $this->handleForm();
 
           if ($result) {
 
               // I redirect on success, when appropriate, in which case 
 
               // I usually omit the else clause and handle the errors 
 
               // without the additional nesting.
 
           } else {
 
               if (isset($this->errorMessage)) {
 
                   $data['errorMessage'] = "Failed to submit form: {$this->errorMessage}";
 
               }
 
           }
 
       }
 
       
        
// Setup the page to view
 
       // ...

 
       $this->load->view('myform/home'$data);
 
   }

 
   protected function handleForm()
 
   {
 
       // get post data
 
       // ...

 
       // validate form
 
       if ($this_>form_validation->run() === false) {
 
           return false;
 
       }

 
       // insert/update data
 
       // ...
 
       if (! $result) {
 
           $this->errorMessage $this->myform_model->errorMessage;
 
           return false;
 
       }

 
       return $result;
 
   }


The method which displays the form simply checks whether the form was posted, and, if it was, it calls another method in the controller to process the form. That method returns false if there was an error, or it can return true (or possibly an ID on a successful insert) if everything is OK. I usually redirect if the form was submitted successfully, because I can send the user to a thank you page or back to a list page, but you can do whatever you like on success. If there's an error (validation or otherwise), it simply sets an error message if one is available, then continues loading the page the same way it would if the user was visiting for the first time.
Reply




Theme © iAndrew 2016 - Forum software by © MyBB