В фреймворке 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>
Результат
Что мы сделали
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 }); });' ); ?>
а использование JS в виде — это вообще нормально?
А где нормально? В контроллере или модели?
нормально — в js-файлах
Я имею ввиду, что $this->registerJs() — это ужасно
Почему?
потому что файлы представления итак сложно содержать в нормальном виде:
php-код, встроенные виджеты Yii2, остаётся только ещё стили подобавлять до кучи и JS
а когда JS-кода станет много, что-то разобрать в коде станет просто нереально
В статье демонстрируется пример, ничего не мешает вам поместить js в отдельный файл
Спасибо! Здорово. $this->registerJs() — нормальная практика, для того и создан))
Спасибо, пост в тему. Использования registerJs тоже избегаю, не люблю мешать логику разных модулей и языков
Добрый день, не работает фильтрация. Указал $query->andFilterWhere([
‘id’ => $this->id,
‘post_id’ => $this->post_id,
но так и отображаются абсолютно все записи из таблицы. Если указываю ‘post_id’ => ‘1’, то фильтр работает нормально. Пожалуйста подскажите в чем проблема.
Смотрите, что приходит в $this->post_id. Без кода представления и searchModel сложно что-то еще посоветовать)
Хотя, вот статья про фильтрацию: http://nix-tips.ru/yii2-sortirovka-i-filtr-gridview-po-svyazannym-i-vychislyaemym-polyam.html
Можно сделать проще, просто форму и грид запихнуть в один 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,
]);
}
}
Тут есть лишний код, но думаю суть ясна.
Ситуация:
есть сообщения и есть форма,.. навешал pjax на форму,.. после pjax:end делаю reload контейнера с сообщениями,..
НО есть 1 проблемка… после всего этого при втором уже заполнении форму форма не уходил через как прежде… а происходит обычная перезагрузка страницы.