В фреймворке 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 проблемка… после всего этого при втором уже заполнении форму форма не уходил через как прежде… а происходит обычная перезагрузка страницы.