Yii2: Примеряем Pjax на ActiveForm и GridView

Yii2 + Pjax

Yii2 + Pjax

В фреймворке Yii 2.0 встроена поддержка jquery плагина pjax, объединяющего pushState и ajax технологии. Подробнее на гитхабе разработчика.

Для примера сделаем возможность добавления новой Заметки в списке заметок без перезагрузки страницы.

Контроллер

    public function actionIndex()
    {
        $model = new Notes();
        if ($model->load(Yii::$app->request->post()) && $model->save())
        {
            $model = new Notes();
        }
        $searchModel = new NotesSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);

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

Шаблоны

index.php

<?php

use yii\helpers\Html;
use yii\widgets\Pjax;
use yii\grid\GridView;

/* @var $this yii\web\View */
/* @var $searchModel app\modules\notes\models\NotesSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */

$this->title = Yii::t('app', 'Notes');
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="notes-index">

    <h1><?= Html::encode($this->title) ?></h1>

    <?= $this->render('_form',[
        'model' => $model,
    ]) ?>

<?php Pjax::begin(['id' => 'notes']) ?>
    <?= GridView::widget([
        'dataProvider' => $dataProvider,
        'filterModel' => $searchModel,
        'columns' => [
            ['class' => 'yii\grid\SerialColumn'],

            'id',
            'note:ntext',
            ['class' => 'yii\grid\ActionColumn'],
        ],
    ]); ?>
<?php Pjax::end() ?>

</div>

_form.php

<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;

/* @var $this yii\web\View */
/* @var $model app\modules\notes\models\Notes */
/* @var $form yii\widgets\ActiveForm */
?>

<?php
    $this->registerJs(
        '$("document").ready(function(){
            $("#new_note").on("pjax:end", function() {
            $.pjax.reload({container:"#notes"});  //Reload GridView
        });
    });'
    );
?>

<div class="notes-form">
<?php yii\widgets\Pjax::begin(['id' => 'new_note']) ?>
    <?php $form = ActiveForm::begin(['options' => ['data-pjax' => true]]); ?>

    <?= $form->field($model, 'note')->textarea(['rows' => 6]) ?>

    <div class="form-group">
        <?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
    </div>

    <?php ActiveForm::end(); ?>
    <?php Pjax::end(); ?>

</div>

Результат

yii2-pjax

Что мы сделали

1. В действии actionIndex добавили сохранение данных новой Заметки, если они пришли в запросе post:

if ($model->load(Yii::$app->request->post()) && $model->save())
        {
            $model = new Notes();
        }

2. Обернули виджеты GridView и ActionForm в пиджак:

<?php Pjax::begin(['id' => 'notes']) ?>
<?php yii\widgets\Pjax::end(); ?>

3. Добавили небольшой скрипт, обновляющий GridView после добавления новой записи:

<?php
    $this->registerJs(
        '$("document").ready(function(){
            $("#new_note").on("pjax:end", function() {
            $.pjax.reload({container:"#notes"});  //Reload GridView
        });
    });'
    );
?>

13 thoughts on “Yii2: Примеряем Pjax на ActiveForm и GridView

      1. Николай

        потому что файлы представления итак сложно содержать в нормальном виде:
        php-код, встроенные виджеты Yii2, остаётся только ещё стили подобавлять до кучи и JS

        а когда JS-кода станет много, что-то разобрать в коде станет просто нереально

        1. Дмитрий

          В статье демонстрируется пример, ничего не мешает вам поместить js в отдельный файл

  1. Туз

    Спасибо! Здорово. $this->registerJs() — нормальная практика, для того и создан))

  2. mogilka

    Спасибо, пост в тему. Использования registerJs тоже избегаю, не люблю мешать логику разных модулей и языков

  3. Алексей

    Добрый день, не работает фильтрация. Указал $query->andFilterWhere([
    ‘id’ => $this->id,
    ‘post_id’ => $this->post_id,
    но так и отображаются абсолютно все записи из таблицы. Если указываю ‘post_id’ => ‘1’, то фильтр работает нормально. Пожалуйста подскажите в чем проблема.

  4. Булат

    Можно сделать проще, просто форму и грид запихнуть в один pjax и все, а контроллер будет выглядеть так:
    public function actionIndex()
    {
    $modelProfit = new Profit();

    if ($modelProfit->load(Yii::$app->request->post()) && $modelProfit->save()) {
    $modelProfit = new Profit();
    $modelProfit->user_id = Yii::$app->user->id;

    $searchModel = new ProfitSearch();
    $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
    return $this->render(‘index’, [
    ‘searchModel’ => $searchModel,
    ‘dataProvider’ => $dataProvider,
    ‘modelProfit’ => $modelProfit,
    ]);
    }else {
    $modelProfit = new Profit();
    $modelProfit->user_id = Yii::$app->user->id;

    $searchModel = new ProfitSearch();
    $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
    return $this->render(‘index’, [
    ‘searchModel’ => $searchModel,
    ‘dataProvider’ => $dataProvider,
    ‘modelProfit’ => $modelProfit,
    ]);
    }
    }
    Тут есть лишний код, но думаю суть ясна.

  5. Виталик

    Ситуация:

    есть сообщения и есть форма,.. навешал pjax на форму,.. после pjax:end делаю reload контейнера с сообщениями,..
    НО есть 1 проблемка… после всего этого при втором уже заполнении форму форма не уходил через как прежде… а происходит обычная перезагрузка страницы.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *