Проблема с $.fn.yiigridview.update, фильтрами, сортировкой, пейджингом, сбрасываемым на нуль

у меня есть CGridview, который обновляется с определенным интервалом. Сортировка, фильтрация и нумерация страниц выполняются с помощью ajax и отлично работают. Проблема в том, что $.fn.yiiGridView.update обновляет сетку с определенным интервалом, из-за чего свойства filter, sort, pagination сбрасываются до нуля, и сетка отображает 1-ю страницу при каждом обновлении.

Это рассматриваемое представление, _productDataGrid.php

    <?php

$this->widget('bootstrap.widgets.TbGridView', array(
    'id' => 'realtime-gridAMZ',
    'itemsCssClass' => 'table table-dark table-striped ',
    'htmlOptions' => array(
        'class' => 'product-datagrid',
    ),
    'dataProvider' => $model->search(),
    'filter' => $model,
    'ajaxUpdate' => 'realtime-gridAMZ',
    'ajaxUrl' => Yii::app()->createUrl('realTime/AjaxUpdate'),

    'pager' => array(
        'header' => '',
        'cssFile' => false,
        'maxButtonCount' => 10,
        'selectedPageCssClass' => 'active',
        'hiddenPageCssClass' => 'disabled',
        'firstPageCssClass' => 'previous',
        'lastPageCssClass' => 'next',
        'firstPageLabel' => '<<',
        'lastPageLabel' => '>>',
        'prevPageLabel' => '<',
        'nextPageLabel' => '>',
    ),
    'summaryCssClass' => 'label label-warning',
    'columns' => array(
        'id',
        'name',
        'category',
        'price'
        'rating'


    ),

));
?>

Вот основное представление index.php, которое изначально отображает сетку при загрузке страницы.

   <div class="box span12" onTablet="span6" onDesktop="span12">
        <div class="box-header">
            <h2><i class="icon-list"></i><span class="break"></span>AMZ</h2>
            <div class="box-icon">
                <a href="#" class="btn-minimize"><i class="icon-chevron-up"></i></a>
                <a href="#" class="btn-close"><i class="icon-remove"></i></a>
            </div>
        </div>
        <div class="box-content">
            <?php
            $this->renderPartial('//realTime/_productDataGrid', array(
                'model' => new RealTime(),
            ));
            ?>
        </div>        
    </div><!--/span-->
</div>


<?php
 $baseUrl = Yii::app()->baseUrl;
        $cs = Yii::app()->getClientScript();
        $cs->registerScriptFile($baseUrl . '/js/ajaxProductDataUpdate.js');
?>

Это файл jquery, который устанавливает таймер и вызывает функцию обновления сетки. ajaxProductDataUpdate.js

    function updateAMZGrid() {
    $.fn.yiiGridView.update('realtime-gridAMZ', {
        data: $(this).serialize()
    });
    return false;
}

$(document).ready(function() {
    setInterval(updateAMZGrid, 60000);

});

И, наконец, это actionAjaxUpdate в RealTimeController, отвечающий за рендеринг ajax.

public function actionAjaxUpdate() {
    $dataProvider = new RealTime();
    $dataProvider->unsetAttributes();

    if (isset($_GET['RealTime']))
        $dataProvider->attributes = $_GET['RealTime'];
    $this->renderPartial('_producDataGrid', array(
        'model' => $dataProvider,
    ));

}

Теперь, как я уже упоминал выше, все функции работают как надо. Но свойство filter, sort, paging сбрасывается при каждом вызове yiiGridViewUpdate. Так, например, если пользователь в данный момент просматривает 24-ю страницу таблицы, через 1 минуту сетка будет обновлена, и он будет перенаправлен на первую страницу таблицы или страницу 1.

То же самое с фильтром, предположим, что пользователь вводит ключевое слово для поиска и просматривает результат, снова через 1 минуту он увидит первую страницу или страницу 1 таблицы, а результат фильтра исчезнет. Таким образом, ему снова придется вводить ключевое слово для поиска в поле фильтра через 1 мин.

Теперь это большое препятствие для любого, кто просматривает данные через сетку.

Кто-нибудь знает, как исправить это? Подскажите, пожалуйста, что мне сделать, чтобы все работало правильно. Я пытаюсь исправить это методом проб и ошибок, но у меня ничего не получается.

Заранее спасибо,

Макс


person Maxx    schedule 22.10.2013    source источник
comment
Кто-нибудь знает исправление для этого. Я отчаянно нуждаюсь в жизнеспособном решении.   -  person Maxx    schedule 22.10.2013


Ответы (1)


Макс. Я взглянул на сгенерированный JS-код для пейджера сетки (когда сетка обновляется ajax):

jQuery('#assortment-grid').yiiGridView({'ajaxUpdate':['assortment-grid'],'ajaxVar':'ajax','pagerClass':'pager','loadingClass':'grid-view-loading','filterClass':'filters','tableClass':'items','selectableRows':1,'enableHistory':false,'updateSelector':'{page}, {sort}','filterSelector':'{filter}','pageVar':'Assortment_page'});

этот самый js заставляет отправлять ajax-запрос на пейджинг сетки следующим образом:

http://srv50213.ht-test.ru/app2/index.php?Assortment[itemSearch]=31351134582, BMW 5 SERIES '85-95 ?28/32/34 FORD MONDEO&Assortment_page=5&ajax=assortment-grid&r=assortment/searchtool

в этом uri есть магические параметры:

  • Assortment_page=5 соотв. для пейджинга
  • Assortment[itemSearch]=31351134582... и Assortment[subgroup]='ДЕТАЛИ КУЗОВА' — отвечают за поддержание фильтрации на стороне сервера:

    if (isset($_GET['realtime-gridAMZ'])) $dataProvider->attributes = $_GET['realtime-gridAMZ'];

  • ajax=assortment-grid соотв. для указания вызова ajax.

Принимая во внимание эти предварительные условия, вы можете попытаться изменить свой код, чтобы он обновлял сетку по таймеру при извлечении сериализованных данных. Здесь вы изменяете некоторые:

 function updateAMZGrid() {
$.fn.yiiGridView.update('realtime-gridAMZ', {
    data: $(this).serialize()
});
return false;
}

вы можете проверить, какие данные передаются через $(this).serialize(), или добавить что-то еще. как $('#realtime-gridAMZ').serialize(). Как насчет того, чтобы проверить $_GET['realtime-gridAMZ_page'] и "скопировать/вставить" его в запрос ajax:

+ '&realtime-gridAMZ_page=' . $_GET['realtime-gridAMZ_page']

таким образом вы получаете текущие данные для повторных запросов. В моем случае это хорошо работает с juiAutoComplete без ajax:

...
'select'=>'js:function(event, ui) {                            
                $(this).val(ui.item.value); 
                location.href= "'. $this->createUrl($this->route) . '&Assortment[itemSearch]=" + ui.item.value + $("#uni-form").serialize() ;   
             }',    

Поэтому вы можете попробовать что-л. похоже на это:

 function updateAMZGrid() {
$.fn.yiiGridView.update('realtime-gridAMZ', {
    data: $(this).serialize() + $('#realtime-gridAMZ').serialize() + + '&realtime-gridAMZ_page=" . $_GET['realtime-gridAMZ_page'] . " 
});
...
return false;

Также проверьте, правильно ли извлекаются параметры GET из запроса XHR на стороне сервера:

`if (isset($_GET['realtime-gridAMZ']))
    $dataProvider->attributes = $_GET['realtime-gridAMZ'];`

почему у вас $dataProvider->attributes = $_GET['realtime-gridAMZ'];, я обычно получаю параметры GET/POST в модель, а не в DataProvider:

 `$model->attributes = $_GET['realtime-gridAMZ'];`

и только после этого

`$dataProvider = $model->search();`

Надеюсь, это поможет вам, не стесняйтесь задавать любые вопросы, если не ясно. Не забудьте инструменты для отладки: F12 или Ctrl+Shift+I

person Igor Savinkin    schedule 21.07.2014
comment
Ничего себе, это действительно краткий обзор 101 по Yii Gridview Advanced... Замечательная информация. Я работал над проблемой взлома хранилища сеансов, но это именно тот ответ, который я искал. Я обновил код в своей системе, чтобы отразить ваш совет. Спасибо. - person Maxx; 23.07.2014
comment
Рад, что помогло. - person Igor Savinkin; 26.07.2014