Filter after sorting problem at GridView

Hi all,

I have a problem here:

Filter after sorting at GridView cause problems.

I have two models:

Product: id, title, img, category_id

ProductCategory: id, alias, name, parent.

The relation of them is declared at:




class Product extends CActiveRecord

{

...

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(

			'category' => array(self::BELONGS_TO, 'ProductCategory', 'category_id'),

		);

	}



At the Product admin page, I have the following code:




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

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

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

	'model'=>$model,

)); ?>

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


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

	'id'=>'product-grid',

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

	'filter'=>$model,

	'pager'=>array(

        'header'=>'',

        'firstPageLabel'=>'<<',

        'prevPageLabel'=>'<',

        'nextPageLabel'=>'>',

        'lastPageLabel'=>'>>',

    ),

	'columns'=>array(

		'id',

		'title',

		'img',		

    	array(

            'name'=>'category_id',

            'value'=>'$data->category->name',

            'filter'=>CHtml::listData(ProductCategory::model()->findAll(), 'id', 'name'),

    		'htmlOptions'=>array('width'=>'90px'),

        ),

		array(

			'class'=>'CButtonColumn',

		),

	),

)); ?>



So that this page will have four columns and the last one will display corresponding product’s category name, and its filter it’s a dropdown list.

Select the dropdown list to filter, it works perfect. I see the request url is:

xxxxx.com/product/admin?Product[id]=&Product[title]=&Product[img]=&Product[category_id]=4&Product_page=1&ajax=product-grid

But, if following :

  1. Select category dropdown list to filter

  2. click other column (for instance id) to sort

  3. Then select category dropdown list to filter again.

It will cause problems:

htmlspecialchars() expects parameter 1 to be string, array given

at CHtml.php

public static function encode($text)

65 {

66 return htmlspecialchars($text,ENT_QUOTES,Yii::app()->charset);

67 }

I saw the request URL at this time is:

xxxxx.com/product/admin/Product[id]//Product[title]//Product[img]//Product[category_id]/3/Product_page/1/ajax/product-grid/Product_sort/id?ajax=product-grid&Product[id]=&Product[title]=&Product[img]=&Product[category_id]=4&Product_page=1

Why it will generate such request at this situation, How can I avoid this if I want use dropdown filter for gridview column. Am I miss anything at Product / ProductCategory model or their controlers?

I would highly appreciate if someone can help me -).

Thanks.

Hi, welcome to the forum !!

It seems a problem related to the rules of the urlManager.

Check the URL Management section of the guide, and it would help you.

URL Management

Thanks for your reply.

I found my issue have some relationship with this topic:

search() + sorting + CDbCriteria

Yes, I am using urlFormat, the following:




'urlManager'=>array(

			'urlFormat'=>'path',

			'rules'=>array(

				// gii required rules

				'gii'=>'gii',

            	'gii/<controller:\w+>'=>'gii/<controller>',

            	'gii/<controller:\w+>/<action:\w+>'=>'gii/<controller>/<action>',

		

				//'<controller:\w+>/<id:\d+>'=>'<controller>/view',

				//'<controller:\w+>/<action:\w+>/<id:\d+>'=>'<controller>/<action>',

				//'<controller:\w+>/<action:\w+>'=>'<controller>/<action>',

				'<controller:\w+>/<action:\w+>/*'=>'<controller>/<action>',

			),

			'showScriptName' => false ,

		),



But why the GridView will generate such URL after I apply this URL rules.

Follow this steps:

  1. Use ProductCategory’s alias field, input “l” to filter;

  2. Then click id field column to sort;

  3. And then use ProductCategory’s alias filed, input “d” to filter.

Will generate this url:

xxxxx.com/productCategory/admin/

ProductCategory%5Bid%5D//

ProductCategory%5Balias%5D/l/

ProductCategory%5Bname%5D//

ProductCategory%5Bparent%5D//

ProductCategory_page/1/

ajax/product-category-grid/

ProductCategory_sort/id

?ajax=product-category-grid

&ProductCategory%5Bid%5D=

&ProductCategory%5Balias%5D=d

&ProductCategory%5Bname%5D=

&ProductCategory%5Bparent%5D=

&ProductCategory_page=1


You can see the second time - input "d" to filter append them to the previous url. Which will cause above problems. The $_GET variables for the filter are now an array and not a string anymore. Why it will do this URL appending under this situation ?

Should I do something with Yii GridView if I want to apply url Path Format? Or should I config something to adapt GridView?.

Thank u for your help.

For gridview to work properly in ajax mode, you have to add a URL rule like the following if you use "path" format:




'<controller:\w+>/<action:\w+>' => '<controller>/<action>'



This will put all filter conditions into the query string part instead of the pathinfo part.

Thanks Qiang!

I trid and it works now. Your explanation is very helpful to me.

Very nice, thank you!

I had to put the modules into the rule too, and then it worked.


'module1/module2/<controller:\w+>/<action:\w+>' => 'module1/module2/<controller>/<action>'

I’m not exactly sure why, but it does the trick :-).

what about not nested modules is this good :


'<module:\w+>/<controller:\w+>/<action:\w+>'=>'<module>/<controller>/<action>'

::)

Thanks Qiang

what about not nested modules is this good :


'<module:\w+>/<controller:\w+>/<action:\w+>'=>'<module>/<controller>/<action>'

That fixed my grid problems, but now when I call createUrl() it generates URLs with the unfriendly format. For example,




/organization/overview/?organizationId=2/



instead of:




/organization/overview/organizationId/2



I’m not sure why that is. Can I have both user friendly urls and ajax-based paging? I’m guessing I am not doing something right.

Thanks for any assistance.