CGridView and pagination

Hi fellas,

first of all, since this is my first post ever, as many other people have to mention: THANK YOU for a "KICK IT!" framework that is so easy and still fast and reliable. You have done a great work doing all of this, so thank you for countless hours of work provided for free.

While working on my first Yii project, I could manage most of the problems myself or by reading the forums / docs, but my current issue really drives me nuts.

I have setup some CHtml Dropdownlists and Textfields together with a CGridView, so one is able to filter data coming from a database via AR. Works like a charm. You enter your search criterias in the CHtml elements, and the CGridView data is filtered accordingly. Problem is: As soon as I choose another page via pagination or sort via columns, the search criterias are gone, and the CHtml elements are all reset to default.

I have read in two bug requests that Qiang recommends to use the urlManager and to remove the "*", which seemed to work for the people who mentioned the problem - but not for me.

I have setup the urlManager properly (as it is defined by yiic initially), have turned on and off AJAX, have tried this and that, without any success whatsoever.

Does anybody have a tip-off if there is any other issue that I’ve ran into? Maybe that the criteria needs to be permanently saved? (At the moment I have it managed via a model->search function, using CDbCriteria).

If anybody needs to see some specific code (I would even provide the whole source to any staff member), if I have forgotten to provide any information or anything else, please let me know.

Cheers,

Frank LaVerne


EDIT: I have found out that if I sort the columns it reflects in the resulting pagination URL (example: index?post_sort=post_id&post_page=xy) and it is also preserved while I "page around", still no clue about the search filters …

Looks like I made a step ahead with my CGridView problem …

I checked the example provided in the blog demo (to be specific: the admin page of the posts where there also is a CGridView) and have registered the javascript for updating the grid in my project (duuuuuuh!) - now it works like it is supposed to, just like in the blog demo. I NEARLY have the result that I want, though I have another strange behaviour now:

1.) I submit the filter via CHtml element (e.g. dropdownlist), it filters.

2.) I submit again OR I select a different page - CHtml elements / filter stays, but the grid is gone (and the URL is not updated)

3.) I submit again - the grid is back (and the URL is finally updated).

Then you can switch between step 2 and 3 which makes the grid appear and disappear.

Anyone has a clue what I did wrong now? :)

Cheers,

Frank


Edit: This could be a bug regarding IE. I tried with Firefox 3.6.10, which works fine, same in Chrome. IE8 has the above mentioned behaviour. Some problem with the gridview js? (Don’t you love to patch your javascripts for IE?)

Second Edit: I’m baffled …

The mentioned behaviour can’t be reproduced in the blog demo, just in my project. What drives me crazy is that during step 2 (when the grid disappears), the URL is not updated. This happens during step 3.

Anybody …?

I’m pretty new at this too, also been working with grid view all day.

No specific suggestions, but posting your relevant view/model/controller code would be helpful.

What version of Yii are you using… previous version to Yii 1.1.4 had problems with IE…

@mdomba:

Thanks for pointing that out - I read about a few issues regarding IE in conjunction with Yii prior to 1.1.4, and I was SO DAMN sure I had updated, but it still was 1.1.2. Nevertheless, I still have the same issues after the update. What I am so confused about is that the blog demo works with IE and doesn’t show the behaviour I have with my project, though I am sure I have reflected all necessary stuff of the blog demo into my project. So, so far I think it still is a mistake in my code somewhere … and still it’s so strange that my project works with Firefox and Chrome without any flaws …

@SystemicPlural:

Since it’s quite some code, I tried to first ask if anything is known about the issue without “spamming the forum” :) But since I so far also don’t see any other chance, here we go:

Controller:




<?php


class ReparaturenController extends Controller

{

	private $_model;


	public function filters()

	{

		return array(

			'accessControl', // perform access control for CRUD operations

		);

	}


	/**

	 * Specifies the access control rules.

	 * This method is used by the 'accessControl' filter.

	 * @return array access control rules

	 */

	public function accessRules()

	{

		return array(

			array('allow', // allow authenticated users to access all actions

				'users'=>array('@'),

			),

			array('deny',  // deny all users

				'users'=>array('*'),

			),

		);

	}


	public function actionIndex()

	{

		$model=new Reparaturen('search');

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

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

		

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

			'model'=>$model,

		));

	}


	/**

	 * Returns the data model based on the primary key given in the GET variable.

	 * If the data model is not found, an HTTP exception will be raised.

	 */

	public function loadModel()

	{

		if($this->_model===null)

		{

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

				$this->_model=Reparaturen::model()->findbyPk($_GET['rep_id']);

			if($this->_model===null)

				throw new CHttpException(404,'The requested page does not exist.');

		}

		return $this->_model;

	}


	public function actionView()

	{

		$model=$this->loadModel();


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

			'model'=>$model,

		));

	}


	/**

	 * Performs the AJAX validation.

	 * @param CModel the model to be validated

	 */

	protected function performAjaxValidation($model)

	{

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

		{

			echo CActiveForm::validate($model);

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

		}

	}

}



Model:




<?php


/**

 * This is the model class for table "tbl_reparaturen".

 */

class Reparaturen extends CActiveRecord

{

	/**

	 * The followings are the available columns in table 'tbl_reparaturen':

	 * @var integer $rep_id

	 * @var integer $rep_hersteller

	 * @var string $rep_type

	 * @var string $rep_gnr

	 * @var string $rep_lsnr

	 * @var string $rep_qname

	 * @var integer $rep_kunde

	 * @var integer $rep_status

	 * @var datetime $rep_wann

	 * @var string $sortherst

	 * @var string $rep_status_text

	 * @var string $rep_kva_jn

	 * @var string $rep_zubehoer

	 * @var string $rep_zst_text

	 * @var string $rep_vpk_text

	 * @var datetime $rep_vers_datum

	 * @var datetime $rep_fertig

	 * @var bool $rep_fertig_bool

	 */


	/**

	 * Returns the static model of the specified AR class.

	 * @return Reparaturen the static model class

	 */

	public static function model($className=__CLASS__)

	{

		return parent::model($className);

	}


	/**

	 * @return string the associated database table name

	 */

	public function tableName()

	{

		return 'tbl_reparaturen';

	}


	/**

	 * @return array validation rules for model attributes.

	 */

	public function rules()

	{

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

		// will receive user inputs.

		return array(

			array('rep_id, rep_type, rep_gnr, rep_lsnr, rep_qname, rep_kunde, rep_status, sortherst, rep_kva_jn, rep_status_text, rep_zubehoer, rep_fertig_bool', 'required'),

			array('rep_hersteller, rep_kunde, rep_status', 'numerical', 'integerOnly'=>true),

			array('rep_type, rep_lsnr', 'length', 'max'=>20),

			array('rep_gnr', 'length', 'max'=>40),

			array('rep_qname', 'length', 'max'=>35),

			array('sortherst', 'length', 'max'=>30),

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

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

			array('rep_id, rep_type, rep_gnr, rep_lsnr, rep_qname, rep_kunde, rep_status, sortherst, rep_status_text, rep_fertig_bool', 'safe', 'on'=>'search'),

		);

	}


	/**

	 * @return array relational rules.

	 */

	public function relations()

	{

		// NOTE: you may need to adjust the relation name and the related

		// class name for the relations automatically generated below.

		return array(

		);

	}


	/**

	 * @return array customized attribute labels (name=>label)

	 */

	public function attributeLabels()

	{

		return array(

			'rep_id' => 'Reparaturnr.',

			'rep_hersteller' => 'Hersteller',

			'rep_type' => 'Gerätetyp',

			'rep_gnr' => 'Seriennummer',

			'rep_lsnr' => 'Ihre Referenz',

			'rep_qname' => 'Kundenname',

			'rep_kunde' => 'Kundennummer',

			'rep_status' => 'Status',

			'rep_wann' => 'Letzte Änderung',

			'sortherst' => 'Hersteller',

			'rep_status_text' => 'Status',

			'rep_kva_jn' => 'Leistungsart',

			'rep_zubehoer' => 'Zubehör',

			'rep_zst_text' => 'Zustand',

			'rep_vpk_text' => 'Verpackung',

			'rep_vk_datum' => 'Verkaufsdatum',

			'rep_vers_datum' => 'Vorauss. Liefertermin',

			'rep_fertig_bool' => 'Abschluss',

		);

	}


	/**

	 * Retrieves a list of models based on the current search/filter conditions.

	 * @return CActiveDataProvider the data provider that can return the models based on the search/filter conditions.

	 */

	public function search()

	{

		// Warning: Please modify the following code to remove attributes that

		// should not be searched.


		$criteria=new CDbCriteria;

		

		$criteria->compare('rep_id',$this->rep_id);


		$criteria->compare('rep_type',$this->rep_type,true);


		$criteria->compare('rep_gnr',$this->rep_gnr,true);


		$criteria->compare('rep_lsnr',$this->rep_lsnr,true);


		$criteria->compare('rep_qname',$this->rep_qname,true);


		$criteria->compare('rep_kunde', Yii::app()->user->name);


		$criteria->compare('rep_status',$this->rep_status,true);


		$criteria->compare('sortherst',$this->sortherst,true);

		

		$criteria->compare('rep_status_text',$this->rep_status_text,true);

		

		$criteria->compare('rep_fertig_bool',$this->rep_fertig_bool,true);


		return new CActiveDataProvider(get_class($this), array(

			'criteria'=>$criteria,

		));

	}

}



View:




<style type="text/css">

td { border:none; padding:0px;}

</style>


<?php

$this->breadcrumbs=array(

	'Reparaturen',

);?>


<?php


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

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

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

		data: $(this).serialize()

	});

	return false;

});

");?>


<div class="search-form">

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

	'model'=>$model,

)); ?>

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


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


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

	'id'=>'reparaturen-grid',

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

	'columns'=>array(

		array(

			'class'=>'CButtonColumn',

			'template'=>'{view}',

		),

		array(

			'class'=>'CLinkColumn',

			'header'=>'<a href="/rapido/index.php/reparaturen/index?Reparaturen_sort=rep_lsnr">Ihre Referenz</a>',

			'labelExpression'=>'$data->rep_lsnr',

			'urlExpression'=>'Yii::app()->createUrl("reparaturen/view",array("id"=>$data->rep_id))',

			'htmlOptions'=>array('style'=>'text-align:center'),

		),

		array(

			'class'=>'CLinkColumn',

			'header'=>'<a href="/rapido/index.php/reparaturen/index?Reparaturen_sort=rep_id">Reparaturnummer</a>',

			'labelExpression'=>'$data->rep_id',

			'urlExpression'=>'Yii::app()->createUrl("reparaturen/view",array("id"=>$data->rep_id))',

			'htmlOptions'=>array('style'=>'text-align:center'),

		),

		array(

			'name'=>'sortherst',

			'htmlOptions'=>array('style'=>'text-align:center'),

		),

		array(

			'name'=>'rep_type',

		),

		array(

			'name'=>'rep_status_text',

		),

		array(

			'name'=>'rep_wann',

            'value'=>'$data->rep_wann',

 			'htmlOptions'=>array('style'=>'text-align:center'),

		),

	),

)); ?>



_Search:




<div class="wide form">


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

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

	'method'=>'get',

)); ?>


<table style="padding:0px;">

	<tr>

	<td style="width:300px">

	<div class="row">

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

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

	</div>

	</td>

	<td style="width:300px">

	<div class="row">

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

		<?php echo CHtml::activeDropDownList($model, 'sortherst', CHtml::listData(Reparaturen::model()->findAll(array('order'=>'sortherst')), 'sortherst', 'sortherst'), array('empty'=>'Keine Auswahl', 'style'=>'width:154px')) ; ?>

	</div>

	</td>

	<td style="width:330px">

	<div class="row">

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

		<?php echo CHtml::activeDropDownList($model, 'rep_fertig_bool', array('false'=>'Offene Aufträge','true'=>'Abgeschlossene Aufträge'), array('empty'=>'Keine Auswahl', 'style'=>'width:200px', 'submit'=>'')) ; ?>

	</div>

	</td>

	</tr>

	<tr>

	<td style="width:300px">

	<div class="row">

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

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

	</div>

	</td>

	<td style="width:300px">

	<div class="row">

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

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

	</div>

	</td>

	<td style="width:330px">

	<div class="row">

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

		<?php echo CHtml::activeDropDownList($model, 'rep_status_text', CHtml::listData(Reparaturen::model()->findAll(array('order'=>'rep_status_text')), 'rep_status_text', 'rep_status_text'), array('empty'=>'Keine Auswahl', 'style'=>'width:200px', 'submit'=>'')) ; ?>

	</div>

	</td>

	</tr>

	<tr>

	<td style="width:300px">

	<div class="row">

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

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

	</div>

	</td>

	<td style="width:300px">

	<div class="row">

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

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

	</div>

	</td>

	<td>

	<div class="row buttons">

		<?php echo CHtml::submitButton('Daten abfragen', array('style'=>'width:200px')); ?>

	</div>

	</td>

	</tr>

	</table>


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


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



So far so good … as mentioned earlier, I have setup the urlManager as suggested by qiang, but have not had any success with that.

I’d be glad about any hint whatsoever!

If you changed now to the new version of Yii could be that the asset folder has old versions inside… just delete all that is there and refresh the webapp page…

Done - sadly without any changes to my problem …

Maybe the following observation could shed some light into the dark:

In Firefox and Chrome, when I filter and page, the URL in the browsers URL bar doesn’t change. In IE, when I click the search button for the first time, there is no change - but when I click it a second time, it changes to something like:

/index.php/reparaturen/index?Reparaturen%5Brep_lsnr%5D=&Reparaturen%5Bsortherst%5D=SAMSUNG&Reparaturen%5Brep_fertig_bool%5D=&Reparaturen%5Brep_id%5D=&Reparaturen%5Brep_type%5D=&Reparaturen%5Brep_status_text%5D=&Reparaturen%5Brep_qname%5D=&Reparaturen%5Brep_gnr%5D=&yt0=Daten+abfragen

… so it sets the right search arguments, but why does it change in IE and not in Firefox / Chrome, and why don’t I have this behaviour in the blog demo when I browse the admin page when I browse it with IE?

This I can repeat on and on - clicking the first time: the gridview disappears, clicking the second time - everythings fine.

mdomba just saved my life solving the issue for me.

To everybody who might also have strange issues with the CGridView like I did: Please check that you open and close your <div> tags correctly. I had a double </div> tag that the IE could not handle!

Thank you Maurizio for your fast help!

You’re welcome

Anyway it’s strange (or not so much) that only in IE it was not working and only on every second search…

For others if interested… in the view posted above this line should be deleted

I have a same problem now. But i can’t do according to what mdomba have said. Because if i delete it my form will not have a closing tag. Now my situation is the CGridView is generated (in a same page but only in portion) after user have click ajaxSubmitButton(after they have choose the choices by dropdownlist). Everything is ok but now i set the pagination page size to 3. And if the output is more than 3 then it will have other pages in the CGridView. But when i clicked the next, previous, first or last which are provided by CGridView, it wont return the rest output and it will return the whole page back to the original(before user select choices).