Displaying Success Messages In Cactiveform

Dear Friends

This post ‘Field validated ,display success messages’ generated interest in me.

I made an attempt to acheive that. I want to share that with you. Kindly go through it and give your valuable inputs to make it better.

I have a model Patient.php.




<?php

class Patient extends CActiveRecord

{   

        public $name; 

        public $age;

	public $sex;

	public $email;

        


        public function rules()

	{

		

		return array(

			array('name,age,sex,email', 'required'),

			array('age','numerical','integerOnly'=>true,'max'=>60,'min'=>'18'),

			array('sex','in','range'=>array('male','female')),

			array('email','email'),

			array('name', 'length', 'max'=>64),

		           );

	}


        

        /**

	* Here we are declaring success messages for each attribute.

	* I have added a tag 'success',to differentiate from normal

	* messages.This is useful in assigning appropriate containers.

	*/ 

	

          public function successMessages()

		{

		     return array(

			'name'=>'Success: You have got a nice looking name.',

			'age'=>'Success: You are fit enough to perform.',

			'sex'=>'Success: You are not an earth worm.',

			'email'=>'Success: Your mail looks like an email.'

			        );

				

		}

}



Displaying Success Messages in Normal Request(Non AJAX):

This can be acheived easily without much work.

PatientController.php




public function actionCreate()

	{

		$model=new Patient;

		$ghost=new Patient;

		$ghostErrors=$ghost->successMessages();

		

	    

		 

		/*Here we are catching the success messages in a separate

		 *object if validation succeeds for a particular attribute.

		 */

		if(isset($_POST['Patient']))

		{

			$model->attributes=$_POST['Patient'];

			$ghost->attributes=$_POST['Patient'];

			foreach($ghostErrors as $attribute=>$message)

			{

				if($model->validate(array($attribute)))

		     	   $ghost->addError($attribute,$message);

			}  

			

			$model->validate(); 

		    

			/*if($model->save())

				$this->redirect(array('view','id'=>$model->id));*/

		}


		$this->render('create',array(

			'model'=>$model,

			'ghost'=>$ghost,

		));

	}



_form.php




<div class="form">


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

	'id'=>'patient-form',

	//'enableAjaxValidation'=>true,

	//'enableClientValidation'=>true,

	)); ?>


	<p class="note">Fields with <span class="required">*</span> are required.</p>


	<?php echo $form->errorSummary($model); ?>


	<div class="row">

		<?php echo $form->labelEx($model,'name'); ?>

		<?php echo $form->textField($model,'name',array('size'=>60,'maxlength'=>64)); ?>

                <?php echo $form->error($model,'name');	

	</div>


 //I have added another container to display success messages


	<div><?php echo $form->error($ghost,'name',array('style'=>"color:darkblue;",'class'=>'flash-success'));?>

..........................................................................................

...........................................................................................

........................>Other form elements.....

        <div class="row buttons">

		<?php echo CHtml::submitButton($model->isNewRecord ? 'Create' : 'Save'); ?>

	</div>


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



When user submits the form, all the errors are displayed as error summary at the top. Beneath the each form element.There may be either an errror message or success message depending on the validation status.

Displaying Success Messages in AJAX Request:

The changes have been made to add a new method for AJAX validation.

PatientController.php




public function actionCreate()

	{

		$model=new Patient;

		$ghost=new Patient;

		$ghostErrors=$ghost->successMessages();

		

	    /*For ajax validation to work I have tweaked method

	     *enableAjaxValidation.

	     */

		$this->ajaxValidate($model,$ghost,$ghostErrors);

		 

		/*Here we are catching the success messages in a separate

		 *object if validation succeeds for a particular attribute.

		 */

		if(isset($_POST['Patient']))

		{

			$model->attributes=$_POST['Patient'];

			$ghost->attributes=$_POST['Patient'];

			foreach($ghostErrors as $attribute=>$message)

			{

				if($model->validate(array($attribute)))

		     	   $ghost->addError($attribute,$message);

			}  

			

			$model->validate(); 

		    

			/*if($model->save())

				$this->redirect(array('view','id'=>$model->id));*/

		}


		$this->render('create',array(

			'model'=>$model,

			'ghost'=>$ghost,

		));

	}




public function ajaxValidate($model,$ghost,$ghostErrors)

	{  

		if(isset($_POST['ajax']) && $_POST['ajax']==='patient-form')

		{ 

			$model->attributes=$_POST['Patient'];

		    $ghost->attributes=$_POST['Patient'];

		    $result=array();

		   

//If validation succeeds for an attribute for regular model,the success message for the //attribute can be added as  error message for ghost model.

		    

		   

			foreach($ghostErrors as $attribute=>$message)

				{

				 if($model->validate(array($attribute)))

				 $ghost->addError($attribute,$message);	 

				}

				

			$model->validate();

			

	 //This is going to add normal error messages to Json object.


			foreach($model->getErrors() as $attribute=>$errors)

				$result[CHtml::activeId($model,$attribute)]=$errors;

				

 //Here we are adding the success messages as error messages to json object 

//from ghost model.

			

			foreach($ghost->getErrors() as $attribute=>$errors)

				$result[CHtml::activeId($ghost,$attribute)]=$errors;

				

			echo function_exists('json_encode') ? json_encode($result) : CJSON::encode($result);

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

		}  

	}



Now every thing is working as expected.Every element is throwing error message

or success message in AJAX manner depending upon the result of validation.

But there are 2 short comings:

1.Every success message is being treated as error message. So it is placed

inside the container with class errorMessage.That is not looking good.

2.We have 2 error fields in our _form.php; one for $model and another for $ghost.

Based on the model class and attribute, YII creates same id for both error fields.

AJAX response updates the both fields with available error messages for the

particular attribute.The result is that we are having 2 error messages.

Both the problems can be overcome by overiding the method

afterValidateAttribute in clientOptions of CActiveForm.

So the finally _form.php looks like this.(My javascript may be nauseating to you.Kindly bear with me).

I am placing the false error messages with prefix success inside container with the class flash-success.

True error messages are placed inside the container with the class flash-error.

I am also changing the colors of input field and label.




<div class="form">


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

	'id'=>'patient-form',

	'enableAjaxValidation'=>true,

	//'enableClientValidation'=>true,

	'clientOptions'=>array('afterValidateAttribute'=>new CJavaScriptExpression("function(form, attribute, data, hasError){

		var id=attribute.id;

		var eid=attribute.errorID;

		

		if(data[id].toString().substring(0,7)=='Success')

		{	$('#'+eid+'.flash-error').css('display','none');

			$('#'+id).parent().children('label.required').css('color','green');

			$('#'+id).css('background','#E6EFC2');

		}

		

		else

		{

			$('#'+eid+'.flash-success').css('display','none');

			$('#'+id).parent().children('label.required').css('color','red');

			$('#'+id).css('background','').addClass('error');

		}

		}")),

		

	)); ?>


	<p class="note">Fields with <span class="required">*</span> are required.</p>


	<?php echo $form->errorSummary($model); ?>


   <div class="row">

	<?php echo $form->labelEx($model,'name'); ?>

	<?php echo $form->textField($model,'name',array('size'=>60,'maxlength'=>64)); ?>

         <?php echo $form->error($model,'name',array('class'=>'flash-error')); ?>

   </div>

	

	<div>

		<?php echo $form->error($ghost,'name',array('style'=>"color:darkblue;",'class'=>"flash-success")); ?>

	</div>	

.........................................................................................

............................................................................................

.....................................Other elements.........>



I hope that there may be better and simpler solution for this.

Expecting valuable inputs.

Regards.

I am attaching a screenshot of AJAX validated form displaying success messages along with error messages.3224

successMessage.png