How To Validate The Advanced Search?

I need to validate one of the searchfields in the gii-generated admin-section(A standard CGridview with the "advanced search")

I tried this in the model:




public function rules()

	{

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

		// will receive user inputs.

		return array(

			...

			array('name, date_first, date_last', 'safe', 'on'=>'search'),

			

			array('date_first', 'compare', 'compareAttribute'=>'date_last', 'operator'=>'>', 'message'=>'Error', 'on'=>'search'), // <-- THIS LINE

		);

	}



I want to compare date_first with date_last, if date_last is an earlier date then date_first I want to display a message and don’t do the search.

When I now try the search nothing happens, the search goes through and no message is shown.

Have I missed something?

try and add the rule to be first in the array

Thanks for the quick reply, I get the same result tho.

Well for this to work, you’ll probably have to disable the standard jQuery code automatically included by Gii, and perform normal validation on the form.

Also, I’m not sure that you can use ‘>’ operator when comparing dates, have you tried it in a normal form (like create or update)?

I’m talking about this


$('.search-form form').submit(function(){

    $.fn.yiiGridView.update('some-grid', {

        data: $(this).serialize()

    });

    return false;

});

I dont know why it does not work for it worked for me, here look at the following screen shot

bennouna’s answer made sense I guess, but if you (alirz23) did get it to work can you post your code?

Dear Adde,

Would you please try this?

If $date_last and $date_first are holding values of DATE or DATETIME or TIMESTAMP, $date_last is greater than $date_first.

Any thing that is going to violate the expression "$date_last > $date_first" is going to throw error.




array(


array('date_last', 'compare', 'compareAttribute'=>'date_first', 'operator'=>'>', 'message'=>'Error', 'on'=>'search'), 


);



OR

We can declare a validator method inside the AR model.





array(


array('date_last', 'compareDate', 'on'=>'search'), 


);


public function compareDate($attribute,$properties)

{

   if($this->date_last < $this->date_first)

      $this->addError($attribute,"$date_last should follow $date_first");


}




Nope, still no luck :confused: Also tried to disable ajax but still the same result.

Dear Adde,

Try to add property format in the rule.

If your date format is like "2012/09/15"

kindly try this.




array(


array('date_last,date_first', 'date', 'format'=>'yyyy/MM/dd', 'on'=>'search'), 

array('date_last', 'compare', 'compareAttribute'=>'date_first', 'operator'=>'>', 'message'=>'Last date should follow first date', 'on'=>'search'), 


);



Dear Adde

I was thinking that problem is only about dealing with validation rules.

The problem here is how we are going to display validation errrors in search form.

I was just beating around validation rules. I feel sorry about that.

I hope I have found solution for that.

1.Modify the _search.php. Add code to display the errors.

fdate and sdate are not actual attributes. Here I have added them as virtual properties.

It was just done to simulate your scenario.




<div class="wide form">


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

	'action'=>Yii::app()->createUrl($this->route),

	'method'=>'get',

)); ?>

 


	<div class="row">

		<?php echo $form->label($model,'username'); ?>

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

		<?php echo $form->error($model,'username'); //This is added.  ?>

	</div>


	<div class="row">

		<?php echo $form->label($model,'email'); ?>

		<?php echo $form->textField($model,'email'); ?>

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

	</div>

	<div class="row">

		<?php echo $form->label($model,'fdate'); ?>

		<?php echo $form->textField($model,'fdate'); ?>

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

	</div>

	<div class="row">

		<?php echo $form->label($model,'sdate'); ?>

		<?php echo $form->textField($model,'sdate'); ?>

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

	</div>


	<div class="row buttons">

		<?php echo CHtml::submitButton('Search'); ?>

	</div>


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


</div><!-- search-form -->




2.Now modify the actionAdmin method in controller.

I have done in the following way.




public function actionAdmin()

	{

		$model=new User('search');

		

		$model->unsetAttributes();  // clear any default values

		$model->clearErrors();      // clear any default errors sticking

		

		if(isset($_GET['User']))

		{	

			$model->attributes=$_GET['User'];

			$model->validate(array('username','fdate','sdate'));//Here just add the attributes you need to validate.

                        $error=$model->hasErrors();

/*If any error occurs we are not going to display the grid. We are going to use $error in cgridview to decide whether we are going to display the grid or not.*/


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

				          'model'=>$model,

				           'error'=>$error

                                     ));

		}	

		else 

		{

			$error=true;//By default we are not displaying the grid

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

				'model'=>$model,

				'error'=>$error,));

		}

	}



3.In admin.php we are going to add $error.

I have displayed just part of the admin.php.

If there is any validation error ,grid will not be displayed.




<?php

//I have commented out the script below.

//At times it prevents errors getting not displayed.

//I think it prevents default behavior of submit button.(2nd script)

?>




/*Yii::app()->clientScript->registerScript('search', "

$('.search-button').click(function(){

	$('.search-form').slideToggle();

	return false;

});

$('.search-form form').submit(function(){

	$.fn.yiiGridView.update('user-grid', {

		data: $(this).serialize()

	});

	return false;

});

");*/




<?php echo CHtml::link('Advanced Search','#',array('class'=>'search-button')); ?>


 <?php //set diplay as block ?>


<div class="search-form" style="display:block">

<?php $this->renderPartial('_search',array(

	'model'=>$model,

)); ?>

</div><!-- search-form -->




<?php if(!$error) //grid is displayed only when there are no validation errors.

         $this->widget('zii.widgets.grid.CGridView', array(

	'id'=>'user-grid',

	'dataProvider'=>$model->search(),

	'filter'=>$model,

	'columns'=>array(

		'id',

		'username',

		'password',

		'email',

		'status',

		array(

			'class'=>'CButtonColumn',

		),

	),

)); ?>



As I have already said fdate and sdate are not actual attributes.

I have made them as virtual properties.

4.Modification in AR model.




class User extends CActiveRecord

{

    public $fdate;

    public $sdate;


    public function rules()

   {  return array(

        array('username', 'required', 'on'=>'search'),

	array('fdate,sdate','date','format'=>'yyyy/MM/dd','on'=>'search'),

	array('sdate','compare','compareAttribute'=>'fdate','operator'=>'>=','message'=>"sdate should   

                    follow fdate",'on'=>'search'),

                  );

   }

}



Althogh the fdate and sdate are not relevant to this model. I have added here

just simulate your scenario. They are nicely displaying errors.

Regards.

Thank you very much! it works, ajax functionality is gone but I think I can live with that!