Ajax Validation doesn't work on CActiveForm

Good morning all,

I’ve followed this http://www.yiiframework.com/doc/api/CActiveForm#enableAjaxValidation-detail and http://www.yiiframework.com/forum/index.php/topic/7940-performajaxvalidation-in-cactiveform/ , I tried to use ajax validation including unique rule in certain model attribute. Please look at my code below.

This is my model rules


public function rules() {

        // NOTE: you should only define rules for those attributes that

        // will receive user inputs.

        return array(

            array('fullName, email, password, username', 'required'),

            array('fullName', 'length', 'max' => 25),

            array('username', 'length', 'max' => 15),

            array('email, password', 'length', 'max' => 60),

            array('password', 'length', 'min' => 6, 'max' => 60),

            array('email', 'email', 'checkMX' => true),

            array('email', 'unique', 'message' => 'Email is already used'),

            array('username', 'unique', 'message' => 'Username is already taken'),

            array('username', 'match', 'pattern' => "/^[A-Za-z0-9_]+$/"),

            // The following rule is used by search().

            // Please remove those attributes that should not be searched.

            array('id, fullName, username, email, password, registerDate', 'safe', 'on' => 'search'),

        );

    }

This is my view


<?php

        $formID = 'register_right';

        $form = $this->beginWidget('CActiveForm', array(

                    'id' => $formID,

                    'method' => 'POST',

                    'action' => 'register',

                    'enableAjaxValidation' => true,

                    'enableClientValidation' => true,

                    'clientOptions' => array(

                        'validateOnSubmit' => true,

                        'validateOnChange' => true,

                        'validateOnType' => true

                    ),

                ));

        ?>

        <div class="row">

            <?php $form->error($model, "fullName"); ?>

            <?php echo $form->textField($model, 'fullName', array('value' => 'Full name', 'class' => 'text_field text_field_register', 'autocomplete' => 'off')); ?>

        </div>


        <div class="row">

            <?php $form->error($model, "email"); ?>

            <?php echo $form->textField($model, 'email', array('value' => 'Email', 'class' => 'text_field text_field_register', 'autocomplete' => 'off')); ?>

        </div>


        <div class="row">

            <?php $form->error($model, "password"); ?>

            <?php echo $form->passwordField($model, 'password', array('value' => 'Password', 'class' => 'text_field text_field_register', 'autocomplete' => 'off')); ?>

        </div>


        <div class="row">

            <?php $form->error($model, "username"); ?>

            <?php echo $form->textField($model, 'username', array('value' => 'Username', 'class' => 'text_field text_field_register', 'autocomplete' => 'off')); ?>

        </div>


        <div class="row buttons">

            <?php

            echo CHtml::ajaxSubmitButton('Register', 'register', array(

                'update' => '#error-panel',

                'type' => 'POST',

                'data' => 'js:$("#' . $formID . '").serialize()',

                'dataType' => 'json',

                'success' => 'js:function(data){

                    if(data.status){

                        location.href = "getstarted/invite";

                    }

                    else{

                        $("#register_error").html(data.message);

                        $("#register_error").show();

                    }

                }'

                    ), array('class' => 'button_1', 'value' => 'Sign up', 'id' => 'register_button'));

            ?>

        </div>

        <div id="register_error"></div>


        <?php $this->endWidget(); ?>

And this is my controller


public function actionIndex() {

        $user = new User;


        $this->performAjaxValidation($user);

        

        $this->layout = "layout_anonymous";

        $this->render('anonymous', array('model' => $user));

    }


    protected function performAjaxValidation($model) {

        if (isset($_POST['ajax'])/* && $_POST['ajax'] === 'user-form'*/) {

            var_dump($_POST);

            echo CActiveForm::validate($model);

            Yii::app()->end();

        }

    }

The client validation works well. But I didn’t see if there is any ajax validation executed, because when i tried to input duplicate attribute, there are no error shown.

If you have any idea, please let me know.

Thx all

To debug AJAX, you need proper tools. Firefox with Firebug, Chrome with its embedded devtools, or (my personal favorite) Operate with its embedded Dragonfly. Open this developer tools (the shortcut is usually Ctr-Alt-I), go to the “network” panel, and see if there are any HTTP requests sent when you think AJAX should be used. If not, go to the “error” panel and see if some JS errors aren’t stopping the process. These are the first steps to track down the bug.

Thx François for the response,

Sorry, I forgot to include those information, the AJAX request actually sent while i’m typing in text field, and no error in browser console.

Or maybe the question become, how I can handle the AJAX response in client side according to my code above?

Thx :)

I think you have missed out in adding the error display for each form fields like for the Ajax validation to work!!! :)

<?php echo $form->error($model, ‘field_name’, array(‘hideErrorMessage’ => true)); ?>

If you run your AJAX request through one of the tools I mentioned, you could see its output. It just displays your var_dump().

You are calling echo on the result of CActiveRecord::validate() which is a boolean. And false converted to string becomes "".

So replace the line


echo CActiveForm::validate($model);

with


echo CHtml::errorSummary($model);

Sidenote:

If you had use &#036;form-&gt;errorSummary(&#036;model) in your view, then AJAX validation should have worked out of the box, without writing one line of JS. See CActiveForm.

@Dyke

Thanks for remind me about that part :)

@François Gannaz

Thank you very much, your answer inspire me to find the solution. I tried using:


echo CHtml::errorSummary($model);

but it doesn’t work to render the error message, because the ajax response needs to be JSON form. But once again your answer is really helpful bro, thanks :)

Below is the working code, i have modified some part in my controller and view codes.

This is my view


<?php

        $formID = 'register_right';

        $form = $this->beginWidget('CActiveForm', array(

                    'id' => $formID,

                    'method' => 'POST',

                    'action' => 'register',

                    'enableAjaxValidation' => true,

                    'enableClientValidation' => true,

                    'clientOptions' => array(

                        'validateOnSubmit' => true,

                        'validateOnChange' => true,

                        'validateOnType' => true,

                        

                        //the code below is only to customize the form's user interface

                        'afterValidateAttribute' => 'js:function(form, attribute, data, hasError){

                            if(hasError)

                                var temp = $("#"+attribute.inputID+"_em_").html();   

                                if(temp)

                                    $("#"+attribute.inputID+"_em_").html("<li>"+temp+"</li>");

                            }

                        ',

                        'afterValidate' => 'js:function(form, data, hasError){

                            $.each(data, function(index, value) { 

                                if(index != "__proto"){

                                    var temp = data[index][0];   

                                    $("#"+index+"_em_").html("<li>"+temp+"</li>");

                                }

                            });

                            if(!hasError)

                                return true;    

                        }'

                    ),

                ));

        ?>

        <div class="row">

            <div class="text_field text_field_register text_field_text">Full name</div>

            <?php echo $form->textField($model, 'fullName', array('class' => 'text_field text_field_register', 'autocomplete' => 'off')); ?>

        </div>


        <div class="row">

            <div class="text_field text_field_register text_field_text">Email</div>

            <?php echo $form->textField($model, 'email', array('class' => 'text_field text_field_register', 'autocomplete' => 'off')); ?>

        </div>


        <div class="row">

            <div class="text_field text_field_register text_field_text">Password</div>

            <?php echo $form->passwordField($model, 'password', array('class' => 'text_field text_field_register', 'autocomplete' => 'off')); ?>

        </div>


        <div class="row">

            <div class="text_field text_field_register text_field_text">Username</div>

            <?php echo $form->textField($model, 'username', array('class' => 'text_field text_field_register', 'autocomplete' => 'off')); ?>

        </div>


        <div class="row buttons  clear_both">

            <?php

            echo CHtml::submitButton('Sign up', array('class' => 'button_1', 'value' => 'Sign up', 'id' => 'register_button'));

            ?>

        </div>

        <div id="register_error">

            <?php echo $form->error($model, "fullName") ?>

            <?php echo $form->error($model, "email") ?>

            <?php echo $form->error($model, "password") ?>

            <?php echo $form->error($model, "username") ?>

        </div>


        <?php $this->endWidget(); ?>

This is my controller


public function actionRegister() {

        $json = array();

        $model = new User;


        if (isset($_POST['ajax']) && $_POST['ajax'] === 'register_right') {

            echo CActiveForm::validate($model);

            Yii::app()->end();

        }


        $model->attributes = $_POST[User];

        if ($model->validate()) {

            $status = $model->insert();

            Yii::app()->getController()->redirect("getstarted/invite");

        } else {

            Yii::app()->getController()->redirect("/");

        }

    }