@xCEZAREx

Как в Yii2 сделать ListView с кастомным фильтром (Ajax/Pjax) и пагинацией?

Добрый день. Подскажите с решением: Необходимо связать ajax обновление данных через кастомную форму с фильтрами и динамической пагинацией.

Сейчас сделал через Pjax.
Представление:
<?php Pjax::begin(); ?>
<?= Html::beginForm(['fields/index'], 'post', ['data-pjax' => '', 'class' => 'form-inline']); ?>
<?= Html::input('text', 'string', '', ['class' => 'form-control']) ?>
<?= Html::submitButton('Search It', ['class' => 'btn btn-lg btn-primary', 'name' => 'hash-button']) ?>
<?= Html::endForm() ?>
    <?= ListView::widget([
        'dataProvider' => $dataProvider,
        'itemView' => '_pjax',
        'options' => [
            'id' => 'listview'
        ]
    ]); ?>
<?php Pjax::end(); ?>


заготовока экшена:
$query = Fields::find();

$query->where(['>=', 'field_value', Yii::$app->request->post('string') ?? 0]);

$dataProvider = new ActiveDataProvider([
    'query' => $query,
]);

return $this->render('index', [
    'dataProvider' => $dataProvider
]);


Выставляю критерии поиска - всё находится, но клик на пагинацию, ListView обновляется без учета фильтра, т.к. пагинатор отсылает данные через GET.

Пробовал через простой ajax обновлять содержимое div в который вывожу еще одну вьюху с ListView как renderPartial, но пагинация перенаправляет на renderPartial этого самого ListView.

Использую ListView, потому-что нужна нормальная пагинация, поэтому нет желания выдумывать велосипед. На форуме Yii2 читал, что Pjax не самое лучшее решение, но пока только с ним добился наиболее оптимального результата. Нашел такой вариант https://toster.ru/q/206776 , в консоль идет ошибка, что id объявленного контейнера не найден, когда подставляю свой - содержимое не обновляется и ошибок нет.

Подскажите, как связать фильтры своей формы и пагинацию, и что бы все обновлялось динамически?

Есть вариант перехватывать клик на пагинатор, но тогда нужно показывать текущую страницу. Если нет решения, то подскажите как переопределить стандартный пагинатор или написать свой.
  • Вопрос задан
  • 2339 просмотров
Пригласить эксперта
Ответы на вопрос 1
Isolution666
@Isolution666
Full-Stack Developer
Ну во первых, надо понимать, что Ajax это технология максимально связана с языком javascript
Чтобы обновлялась информация по Ajax, нужно создать поле (DOM-дерево), с неким id, которое будет привязано к функции.
Pjax это лишь вспомогательный класс, инструмент, для манипуляции с контентом, поэтому сети блока с классом Pjax надо раскинуть ровно на столько, на сколько это будет касаться обновления контента. В некоторых случаях мне приходилось захватывать во вью всю страничку экшена, паганацию можно вывести отдельно, вне ListView, и эта технология описана в документации Yii2

Вот пример рабочего экшена, пусть написано криво, но сообщения отсылаются мгновенно и без перезагрузки страницы, со временем я сделаю этот код более удобным и простым:
public function actionMessages($id ='', $token ='')
    {

        $model = new Message(); // обращаемся к классу привязанному к таблице БД
            if ($model->load(Yii::$app->request->post()) && $model->save()) // убеждаемся что передача данных проходит успешно
            {
                $model = new Message(); // возвращаем то что обновили
            }    

        $send = Message::find()->where(['token' => $token])->orderBy(['id' => SORT_ASC ])->all(); // выводим всю переписку с конкретным пользователем
        $col = Message::find()->where(['token' => $token])->count(); // выводим количество сообщений с конкретным пользователем (например, чтобы скрыть пустой код, если переписки ещё не было)
        $getm = User::find()->where(['id' => $id])->one(); // так мы определим с кем мы переписываемся (имя, аватарка, возраст, что угодно)
        
        return $this->render('messages', ['model' => $model, 'col' => $col, 'send' => $send, 'getm' => $getm, 'id' => $id, 'token' => $token,]); // рендерим всё к чему прикоснулись, чтобы работало.
    }

Вроде всё понятно, и это всё работает внутри "пиджака", через javascript по конкретному id в блоке div возможно кто-то уже нашёл готовое решение, я лишь делюсь своим скромным опытом.
Что касается конкретно класса пагинации:
<?php
use yii\data\Pagination;
?>

Это класс хорошо работает с классом:
<?php
use yii\widgets\LinkPager;
?>

Который надо прописать во вью, и прописать вот такую не хитрую конструкцию:
<?php echo LinkPager::widget(['pagination' => $pages,]);?>

Там, где следует отобразить саму пагинацию. Как говорилось выше, надо применить некий id к коду выше, думаю как прописать это в коде - вы знаете, если вдруг фокусы с ListView не прошли.
Никому не нужны костыли, но если нужно срочно что-то решать, то сойдёт и рабочий код:
Controller::action /
$query = Guestbook::find()->where(['level' => 1])->orderBy(['time' => SORT_DESC,]); // создаём конструкцию обращения
        $pages = new Pagination(['totalCount' => $query->count(),'pageSize' => 5]); // обращаемся к классу чтобы сказать сколько записей за раз нужно отобразить, например 5
        $pages->pageSizeParam = false; // отключаем самодеятельность параметров
        $models = $query->offset($pages->offset)->limit($pages->limit)->all(); // теперь зная количество записей и лимиты, мы заставляем скрипт показывать нам ровно столько сколько нам нужно


На сколько мне известно, теги и айдишко можно прописать и в самом ListView , класс не привередливый, лёгкий и гибкий, решает практически все потребности и капризы заказчиков, почитай о всех возможностях здесь: https://xn--d1acnqm.xn--j1amh/%D0%B7%D0%B0%D0%BF%D... и здесь: www.yiiframework.com/doc-2.0/yii-widgets-linkpager.html думаю это будет приятным чтивом, потому как тут очень много ответов и решений.
ну и наконец ссылочка, которая лично мне очень помогла: https://nix-tips.ru/examples/simplegridview/index

Благодарю за внимание.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы