Pagination

Hello folks!

I hope someone can help me solve a pagination issue, as I can’t find any post that describes how to deal with this.

The case is that I have a search form, where I search for stores (search.php). When I hit the search button, an ajax request is sent to my controller, and the matching stores are listed in a separate view by using renderPartial (_searchResult.php). Everything is displayed as expected, but something is wrong with the pagination. A non-ajax get request is sent to my controller when I click "next", causing only a blank page to appear. How do I get the pagination links to use ajax, as expected?

Controller code:




public function actionSearch()

{

        $model = new StoreSearchForm();


        if(Yii::app()->request->isAjaxRequest)

        {

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

            {

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


                $model->SearchResult = new CArrayDataProvider(Store::model()->search($model->SearchString), array(

                    'pagination'=>array(

                        'pageSize'=>15

                    )

                ));


                $this->renderPartial('_searchResult',array('dataProvider'=>$model->SearchResult), false, true);

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

            }

        }


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

}



view search.php:




<div class="form">

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

	    'id'=>'store-search-form',

	    'enableAjaxValidation'=>false,

    )); ?>


    <div style="float: left;">

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

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

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

    </div>


    <div class="buttons" style="float: left;">

        <?php echo CHtml::ajaxSubmitButton(Yii::t('app','Search'),'search',array(

			'update'=>'#searchResultContainer'

	    ),array('id'=>'btnSearchStore', 'style'=>'margin: 20px 0 0 5px;')); ?>

    </div>


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

</div>


<?php echo CHtml::tag('h2', array('style'=>'clear: both; padding-top: 40px;'), Yii::t('app', 'Search results')); ?>

<div id="searchResultContainer">

	<p><?php echo Yii::t('app', 'No search has been executed yet'); ?></p>

</div



View _searchResult:




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

        'dataProvider'=>$dataProvider,

        'itemView'=>'_searchResultItem',

        'itemsTagName'=>'table',

        'id'=>'#searchResultList',

)); ?>



Any tips that could lead me in the right direction? :)

Post here the Store->search() method. I have a hunch but I can’t say without the contents of that method.

Thanks for the reply. The Store->search() function looks like this:




 public function search($searchString)

    {

        $this->searchString = $searchString;

        $response = $this->query('search', 'GET');


        return $this->populateRecords($response->getData());

    }



I guess it doesn’t tell you much though. I use the extension EActiveResource to communicate with a REST API, and it’s just too much to display all the underlying code, but I can dig up some more info if you are looking for something specific.

Indeed it doesn’t help a lot :)

My suspicion was in the direction of searching on related items where the relationship is ONE_MANY or MANY_MANY. The problem is explained in this forum thread.

I recommend checking if you’re falling into the exact same pit. The thread also includes a solution, described in comment #5 of it, but I’m not sure that its applicable with the extension you’re using, with which I have no familiarity.

Actually I don’t use any relations at all in this case. I am just using a single Store model.

Try using ‘get’ method in your form and check $_GET in your controller, instead of ‘post’ and $_POST.

Hmm… this is weird. I set the form to use GET, like this:




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

    'id'=>'store-search-form',

    'method'=>'get',

    'enableAjaxValidation'=>false,

)); ?>



… but it still sends a post-request. What is going on??

Probably you have to change the ajaxSubmitButton to use ‘get’ method accordingly.

[EDIT]

jQuery.ajax() use ‘get’ by default … so the suggestion above doesn’t make sense.

Sorry.

I changed the ajaxSubmitButton like this:




<div class="buttons" style="float: left;">

    <?php echo CHtml::ajaxSubmitButton(Yii::t('app','Search'),'search',array(

        'type'=>'GET',

	'update'=>'#searchResultContainer'

    ),array('id'=>'btnSearchStore', 'style'=>'margin: 20px 0 0 5px;')); ?>

    </div>



Still sending post-requests. I have emptied the assets folder and cleared browser history without any effect…

Oh, I’m sorry. :-X

The default value of ‘type’ is ‘GET’, so my previous suggestion didn’t make sense.

http://api.jquery.com/jQuery.ajax/

Well, then what’s wrong, I wonder.

Do you have any JavaScript issues that may crash your scripts? You could use the Chrome’s developer tools to check that. Other than that I see a wrong id property in your listview. ‘id’=>’#searchResultList’ would render <tag id="#searchResultList" /> which isn’t valid, so don’t use the hash as it will be prepended

Dear Skukji

The following code may look very stupid!

But please try this.

Controller code.




public function actionSearch()

{

        $model = new StoreSearchForm();


        if(Yii::app()->request->isAjaxRequest)

        {

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

            {

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

                Yii::app()->user->setState('searchForm',$model);

            }


            if(Yii::app()->user->hasState('searchForm'))

            {


                $model=Yii::app()->user->getState('searchForm');

            }


                $model->SearchResult = new CArrayDataProvider(Store::model()->search($model->SearchString), array(

                    'pagination'=>array(

                        'pageSize'=>15

                    )

                ));


                $this->renderPartial('_searchResult',array('dataProvider'=>$model->SearchResult), false, true);

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

            

        }


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

}




When I want to construct a page with CGridView or CListView, I always use gii-generated "admin" page (and/or "index" page) as a skeleton or a template.

I would do something like.

controller




public function actionSearch()

{

	$model = new Store('search');

	$model->unsetAttributes();


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

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


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

}



This is almost exactly the same with gii-generated "actionAdmin".

view … searchResult.php




...

<div class="search-form">

<?php $this->renderPartial('_searchForm',array('model' => $model,)); ?>

</div>

...

<?php

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

	'itemView'=>'_searchResultItem',

	'itemsTagName'=>'table',

	'id'=>'searchResultList',

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

));

...

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

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

	$.fn.yiiListView.update('searchResultList', { /* slight modification */

		data: $(this).serialize()

	});

	return false;

});

");



This is based on the gii-generated "admin.php" view script.

I used CListView instead of CGridView. So I modified the javascript just a litte.

partial view … _searchForm.php




<div class="form">

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

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

	'method' => 'get',

)); ?>

<div class="row" style="float: left;"">

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

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

</div>

<div class="row" buttons style="float: left;">

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

</div>

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

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



This is also a slight modification of gii-generated "_search.php" partial view script.

In the above, ‘name’ is some attribute of Store model … you may want “SearchString” here, of course you can. But for the moment, just use one of the existing attributes of Store.

That’s all. It should work as expected, including the ajax updating functionality.

Fairly easy, isn’t it?

Thank you very much! This solved my problem :)

Thanks, softark. I will look into this too!