4

I have a basic ajax form on my site utilizing the Js helper, it works fine but when there are validation errors the update callback duplicates the entire page inside of my success div.

Success div:

<div id="success"></div>

Submit button:

echo $this->Js->submit('Send', array(
    'before'=>$this->Js->get('#sending')->effect('fadeIn'),
    'success'=>$this->Js->get('#sending')->effect('fadeOut'),
    'update'=>'#success',
    'class'=>'btn btn-primary'
));

Javascript:

$(document).ready(function(){

    $('#postkey, #gender, #hair, #location, #message').blur(function(){
        $.post(
            '/Cake_ajax/Posts/validate_form',
            { field: $(this).attr('id'), value: $(this).val() }
            //handleNameValidation
        );
    });

});

Validate form function in my controller:

public function validate_form(){
    if($this->RequestHandler->isAjax()){
        $this->request->data['Post'][$this->request['data']['field']] = $this->request['data']['value'];
        $this->Post->set($this->request->data);
        if($this->Post->validates()){
            $this->autorender = FALSE; // don't render a view
            $this->set('error','');
        }else{
          $this->layout ="ajax";
            $this->autoRender = FALSE;
            $error = $this->validateErrors($this->Post);
            $this->set('error',$this->Post->validationErrors[$this->request['data']['field']][0]);  
        }
    }
}

I don't know if this is enough information to go on, If I need to post more code, just let me know.

thanks.

4
  • If this is a direct copy paste, did you try changing the line to $this->autoRender = false (with a capital R)? Also, which layout is used as the default? Commented Apr 27, 2012 at 20:55
  • I think [CakePHP Form Validation with Ajax Using jQuery][1] will be useful for setting up an ajax validation in CakePhp [1]:jamnite.blogspot.com/2009/05/… Commented May 1, 2012 at 5:51
  • Cheers!! I was looking for a solution to the same problem and your accepted answer solved my issue. Commented Jul 5, 2012 at 7:15
  • Such a great feeling when you google a problem you're having and someone's had the same one and it's been solved :) Good luck with your project. Commented Jul 5, 2012 at 22:07

6 Answers 6

4

I just tested your application by using your zip file.

What I observed is that this is not the whole page that is put inside your #success div, but only the content of the Posts/add.ctp view. So basically this means the RequestHandler does its job correctly, meaning the layout that is used is the 'ajax' layout. To get rid of anything else that the form, the add.ctp page should not contain anything else that the form. In your case Posts/add.ctp contains navigation links, and that's why they get duplicated.

That said, what the submit button does currently is getting the content of Posts/add.ctp view and insert it in your empty #success div. But you never remove the form that was already on the page. What you could do is updating the content of a div that contains your first form, or even the content of the whole Posts/add.ctp view.

In your case, simply updating the #content instead of the #success div could maybe suit your needs:

echo $this->Js->submit('Send', array(
  'before'=>$this->Js->get('#sending')->effect('fadeIn'),
  'success'=>$this->Js->get('#sending')->effect('fadeOut'),
  'update'=>'#content',
  'class'=>'btn btn-primary',
  'controller'=>'posts',
  'action'=>'add'
));
Sign up to request clarification or add additional context in comments.

4 Comments

That works great, thank-you. Just now how can I render a success message without it replacing the whole add.ctp page with the success.ctp?
I don't use the JsHelper myself, but prefer to write my own jQuery scripts to have more control on what the script does. But in your case, I think rendering a different view from the Controller like you do is the thing to do. If the question is to figure how to make the menu not disappear, well, you could update the form only (instead of #content) but render in the view only the part you need (the form if you have error, or a success message). But in this case, do not render the menu if the request is an Ajax call.
Note that if you do need to have the action menu or whatever in add.ctp, you could also achieve this by sending the Ajax request to another action that would render the form in case of error or a success message.
You never accepted my answer. It was not what you were looking for ?
1

I ran into the same problem. Although nIcO seems to be giving the solution, in my case it didn't helped, because the success message Drawrdesign wants, is still not being rendered.

So, I looked at your zip file and found the solution. There are two ajax calls defined: 1) the .blur and 2) the .bind. 1) is used for validation of the fields and submits data through AJAX to the validate_form() function of the PostsController. And 2) is used to observe the click event of the submit button and sends data to the add() function of the PostsController.

This problem occurs at 2), because you click the Submit button. So, you should be looking at the add() function of the PostsController. In the validate_form() of 1) function you added the line:

$this->autoRender = FALSE; 

And this is the solution. Because where CakePHP automatically renders the view, you don't want it to happen, because of AJAX. So, in case 1) it's done, it should be added to the add() function in the case 2) like this:

public function add() {
// Ajax post
if(!empty($this->request->data)) {
    // ...
    $this->autoRender = FALSE; // ** NEW LINE **
        if($this->Post->save($this->request->data)) {
            // ...     
        } 
        // ...
    } 
    // ...
} 

So, it's stop of (auto)rendering the add.ctp in the div="#success", and your other messages of "sending.." and "succes.ctp" are still begin displayed.

PS. @Drawrdesign, did you by any chance followed an instruction video of andrewperk?

Comments

0

in the Ajax Request handling set the layout to ajax. So the error message will be rendered with the ajax layout and not with the default layout.

UPDATED

public function validate_form(){
if($this->RequestHandler->isAjax()){
    $this->request->data['Post'][$this->request['data']['field']] = $this->request['data']['value'];
    $this->Post->set($this->request->data);
    if($this->Post->validates()){            
        $this->autoRender = FALSE; // don't render a view
        $this->set('error','');
    }else{
        $this->layout ="ajax";
        $this->autoRender = FALSE; 
        $error = $this->validateErrors($this->Post);
        $this->set('error',$this->Post->validationErrors[$this->request['data']['field']][0]);  
    }
}

}

4 Comments

Hey, thanks for the reply. Unfortunately that didn't fix the problem. It's really starting to grind my gears, haha.
@Drawrdesign : There was a mistake I should have added the layout settings in the else part. Updated the code now please try now.
Still no :( Can I zip up the entire app for you to have a look at? Or pastebin it, or something?
thanks, here's a link to the .zip file: drawrdesign.com/wp-content/uploads/2012/04/Cake_ajax.zip
0

Make sure you are either:

Using the RequestHandler component (preferred):

class AppController {

    var $compontents = array('RequestHandler');

}

or manually set the layout to 'ajax' in your action:

$this->layout = "ajax"

Request handler will set the layout to ajax automatically when it detects an Ajax request.

The ajax layout doesn't return anything other than the rendered view.

1 Comment

I already had the request handler in my controller, and tried the ajax layout, but no dice.
0

Hello firstly it seems you are using cake 2 lib and using 1.3 code which will probably work but is in parts deprecated may be work checking the migration guide . The console tool can also upgrade your code to 2.0/2.1 .

Secondly surely you do want to render a view and an empty layout? $errors is defined in Views/Posts/validate_form.ctp. You are setting $errors and then not rendering the view. Remove setting the auto render to false and place at the top of you controller action.

$this->layout = 'ajax';
Configure::write("debug",0);

Any good?

Comments

0
public function admin_edit_comment() {
    $this->layout = 'ajax';
    $this->autoRender = false;
    if ($this->request->is('ajax')) {
        if ($this->FaComment->save($this->request->data, false)) {
            $response['status'] = 'success';
            $response['action'] = 'edit_comment';
            $response['data'] = $this->request->data['FaComment'];
            $response['message'] = __d('vanderdeals', 'Comment saved successfully');


    } else {
            $response['status'] = 'error';
            $response['model'] = 'FaComment';
            $response['message'] = __d('vanderdeals', 'Internal server error occurred. Please try again later.');
        }

        echo json_encode($response);
    }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.