Yii2: Updating Grid-view using Pjax - php

Following this Wiki Yii 2.0: Pjax on ActiveForm and GridView - Yii2
I have tried to use my gridview to update on Ajax without page-reload, but couldn't succeed.
code of my _form.php
<?php
$this->registerJs(
'$("document").ready(function(){
$("#new_medicine").on("pjax:end", function() {
$.pjax.reload({container:"#medicine"}); //Reload GridView
});
});'
);
?>
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use kartik\grid\GridView;
//use yii\grid\Gridview;
use yii\data\ActiveDataProvider;
/* #var $this yii\web\View */
/* #var $model app\models\Medicine */
/* #var $form yii\widgets\ActiveForm */
?>
<!-- <div class="row">
<div class="col-lg-6 col-lg-offset-3"> -->
<div class="medicine-form">
<?php yii\widgets\Pjax::begin(['id' => 'new_medicine']) ?>
<?php $form = ActiveForm::begin(['options' => ['data-pjax' => true ]]); ?>
<?= $form->field($model, 'medicine_id')->textInput(['maxlength' => 10]) ?>
<?= $form->field($model, 'medicine_name')->textInput(['maxlength' => 50]) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
<?= Html::submitButton($model->isNewRecord ? 'Save & New' : '',$option=['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary','name'=>'save_and_new']) ?>
</div>
<?php ActiveForm::end(); ?>
<?php yii\widgets\Pjax::end() ?>
</div>
Code in my controller
public function actionIndex()
{
$model = new Medicine();
if ($model->load(Yii::$app->request->post()) && $model->save())
{
$model = new Medicine(); //reset model
}
$searchModel = new MedicineSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model' => $model,
]);
}
code in index.php
<?php
use yii\helpers\Html;
use yii\grid\GridView;
/* #var $this yii\web\View */
/* #var $searchModel app\models\MedicineSearch */
/* #var $dataProvider yii\data\ActiveDataProvider */
$this->title = 'Medicines';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="medicine-index">
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p>
<?= Html::a('Create Medicine', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?php \yii\widgets\Pjax::begin(['id' => 'medicine']); ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'id',
'medicine_id',
'medicine_name',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
<?php \yii\widgets\Pjax::end(); ?>
</div>
I think I have followed the instructions very carefully, but surely I am missing something as the grid-view is not showing the new records added without page-reload.
Any help will be greatly appreciated.
Thanks.

try to explain how to do it as a widget; it's a generic solution, so contact me in case of troubles:
Controller (#your-alias/controllers/yourController):
...
public function actionManage($param=''){
$model = new YourModel();
if (Yii::$app->request->isPjax && $model->load(Yii::$app->request->post()) && $model->save())
{
$model = new YourModel(); //reset model
}
$model->paramId = $param;
$queryParams = Yii::$app->request->getQueryParams();
$queryParams['YourModelSearch']['param'] = $param;
$searchModel = new YourModelSearch();
$dataProvider = $searchModel->search($queryParams);
return $this->renderAjax('#your-alias/widgets/views/index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
'model' => $model,
]);
}...
widgets (#your-alias/widgets/) [form, view]:
_form:
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\widgets\Pjax;
/**
* #var yii\web\View $this
* #var yourModule/models/YourModel $model
* #var yii\widgets\ActiveForm $form
*/
?>
<?php
$js = <<<JS
// get the form id and set the event
$('form#{$model->formName()}').on('beforeSubmit', function(e) {
var \$form = $(this);
// do whatever here, see the parameter \$form? is a jQuery Element to your form
console.log(\$form);
console.log("MODEL CODE = " + $("#yourmodel-code").val());
}).on('submit', function(e){
e.preventDefault();
});
JS;
//$this->registerJs($js);
$this->registerJs(
'$("#new-your-model").on("pjax:end", function() {
commonLib.divAction("#div_new_model", "hide"); //hide form
$.pjax.reload({container:"#models"}); //Reload GridView
});', \yii\web\View::POS_READY
);
?>
<div class="model-form">
<?php Pjax::begin(['id' => 'new-model', 'timeout' => false, 'enablePushState' => false]) ?>
<?php $form = ActiveForm::begin([
'id' => $model->formName(),
//'method' => 'post',
'action' => ['/module/controller/manage?param='.$model->code],
'options' => ['data-pjax' => true ],
//'layout' => 'default',
]); ?>
<?= $form->field($model, 'code')->textInput(['maxlength' => 255]) ?>
...
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
<?php yii\widgets\Pjax::end() ?>
</div>
index view (grid view):
use yii\helpers\Html;
use yii\grid\GridView;
use yii\widgets\Pjax;
/**
* #var yii\web\View $this
* #var yii\data\ActiveDataProvider $dataProvider
* #var yourModule\models\search\YourModelSearch $searchModel
*/
?>
<div class="model-index">
<!--h1><!--?= Html::encode($this->title) ?></h1-->
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p>
<?= Html::button(Yii::t('bp', 'Add ...'), [
'class' => 'btn btn-success',
'onclick'=>'js:commonLib.divAction("#div_new_model", "show")'
])?>
</p>
<div id="div_new_model" style="display:none">
<?= Html::button(Yii::t('common', 'Cancel'), [
'class' => 'btn btn-success',
'onclick'=>'js:commonLib.divAction("#div_new_model", "hide")'
])?>
<!-- Render create form -->
<?= $this->render('_formModel', [
'model' => $model,
]) ?>
</div>
<?php Pjax::begin(['id' => 'models', 'timeout' => false, 'enablePushState' => false]) ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
...
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
<?php Pjax::end() ?>
</div>
widget call (in view):
echo #your-alias\widgets\YourWidget::widget([
'param' => $model->param,]);

$.pjax.reload('#my-grid-pjax' , {timeout : false});

To update GridView table without page reload using pjax:
use yii\grid\GridView;
use yii\widgets\Pjax;
Pjax::begin(['id' => 'todaysactivity', 'timeout' => false, 'enablePushState' => false])
Use jQuery/JavaScript as follows:
var url = baseurl + '/activity/logging'; // url where the gridview table need to update
$.pjax.reload({container: "#todaysactivity", url: url}); // refresh the grid

I couldn't find a suitable solution to update the grid-view widget using pjax.
I resolved by using a auto-refresh method for the grid-view page. I understand that this is not the best solution and I am still looking for a suitable solution.
The method I have used is like this:
<script>
function autoRefresh()
{
window.location.reload();
}
setInterval('autoRefresh()', 60000); // this will reload page after every 1 minute.
</script>

What you're looking for is
<script type="text/javascript">
$.pjax.defaults.timeout = false;
</script>
The default pjax timeout setting doesn't give the page time to do anything so it reloads.
Reference

Related

Yii2 dropdown list and array helper "Call to a member function isAttributeRequired() on array"

I am trying to understand why my drop down list is not working. I recieve the following error messages when I try to run the custom view related to this model/view/controller.
Please forgive any of my ignorance as I am completely new to PHP and PHP frameworks by proxy.
Site Controller Code:
public function actionStudentcentrequiz()
{
$model = new GameId();
$qnamodel = new Questions();
$listData = ArrayHelper::map(Gameid::find()->all(), 'gameid','gamename');
if ($qnamodel->load(Yii::$app->request->post())) {
//PK FK relation
$model->gameid = $qnamodel->gameid;
if ($qnamodel->validate()) {
//var_dump($qnamodel); die;
//then save.
$qnamodel->save();
}
//form inputs are valid, do something here
return;
}
return $this->render('studentcentrequiz', [
'model' => $model,
'qnamodel' => $qnamodel,
'listData' => $listData,
]);
}
view/questions/_form.PHP
use yii\helpers\Html;
use yii\widgets\ActiveForm;
/* #var $this yii\web\View */
/* #var $model app\models\Questions */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="questions-form">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'Question')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'Answer1')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'Answer2')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'Answer3')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'Answer4')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'gameid')->dropDownList($listData,['prompt'=>'ChooseGameID']) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
view/questions/_create.PHP
<?php
use yii\helpers\Html;
/* #var $this yii\web\View */
/* #var $model app\models\Questions */
$this->title = 'Create Questions';
$this->params['breadcrumbs'][] = ['label' => 'Questions', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="questions-create">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', ['model' => $model, 'listData' => $listData,
]) ?>
</div>
view/questions/_update.PHP
<?php
use yii\helpers\Html;
/* #var $this yii\web\View */
/* #var $model app\models\Questions */
$this->title = 'Update Questions: ' . $model->questionID;
$this->params['breadcrumbs'][] = ['label' => 'Questions', 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model->questionID, 'url' => ['view', 'id' => $model->questionID]];
$this->params['breadcrumbs'][] = 'Update';
?>
<div class="questions-update">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', ['model' => $model, 'listData' => $listData,]) ?>
</div>
Well, after 2 hours with the same problem
View:
$form->field($model[0], 'gameid')->dropDownList($listData,['prompt'=>'ChooseGameID'])
Why? i dont know, I would like to someone explain, I have 41 records and both appear the same way in the dropdownlist [0][1][2]...

When value in dropdownlist have ever been selected will not display

I have two tables that relate to each other one to one that is Husband and Wife. I've made my value dropdownlist and to get the data from the table Husband. I want when its value had been chosen will not appear on his dropdownlist. Perhaps there are other references or can be helped. For the code can be seen in the image below.
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use app\models\Husband;
/* #var $this yii\web\View */
/* #var $model app\models\Wife */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="wife-form">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'id_husband')->dropDownList(
ArrayHelper::map(Husband::find()->where('status' => 0)->all(), 'id_husband', 'name'),
['prompt' => 'Pilih']
) ?>
<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'status')->dropDownList(['0' => 'Tidak Aktif', '1' => 'Aktif'],
['prompt'=>'--Pilih--', 'style' => 'width:380px']) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
You forgot to mention as array in the where condition .
Use ->where(['status' => 0])" instead of "->where('status' => 0)
So it is:
<?= $form->field($model, 'id_husband')->dropDownList(
ArrayHelper::map(Husband::find()->where(['status' => 0])->all(), 'id_husband', 'name'),
['prompt' => 'Pilih']
) ?>

Handling breadcumbs on ajax yii2

I have a breadcumbs in yii2. The problem is, I am using pjax to handle crud of my table on database.
Let say, this is my code (in index.php in view):
<?php
$this->title = 'Barangs';
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="barang-index">
<?php
Pjax::begin([
'timeout' => 5000,
'id' => 'pjax-gridview'
]);
?>
<h1><?= Html::encode($this->title) ?></h1>
<?php // echo $this->render('_search', ['model' => $searchModel]); ?>
<p>
<?= Html::a('Create Barang', ['create'], ['class' => 'btn btn-success']) ?>
</p>
<?=
GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'NO_URUT',
'CONSIGNEE',
'CONTAINER',
'SIZE',
'COIL_NO',
'NET',
'GROSS',
'CONTRACT_NO',
'KET',
'NAMA_FILE',
'TGL_UNSTUFF',
['class' => 'yii\grid\ActionColumn',
'buttons' => [
'view' => function($url, $model) {
$icon = '<span class="glyphicon glyphicon-eye-open"></span>';
return Html::a($icon, $url);
},
'update' => function($url, $model) {
$icon = '<span class="glyphicon glyphicon-pencil"></span>';
return Html::a($icon, $url);
},
'delete' => function($url, $model) {
$icon = '<span class="glyphicon glyphicon-trash"></span>';
return Html::a($icon, $url, [
"class" => 'pjaxDelete'
]);
},
]
],
],
]);
?>
<?php $this->registerJs('
/* fungsi ini akan dijalankan ketika class pjaxDelete di klik */
$(".pjaxDelete").on("click", function (e) {
/* cegah link menjalankan default action */
e.preventDefault();
if(confirm("Are you sure you want to delete this item?")){
/* request actionDelete dengan method post */
$.post($(this).attr("href"), function(data) {
/* reload gridview */
$.pjax.reload("#pjax-gridview",{"timeout":false});
});
}
});
');
?>
<?php Pjax::end(); ?></div>
My question is, without ajax, breadcumbs will be show Home / Barangs / Create Barang. But in ajax, the breadcumbs looked this : Home / Barangs /
I still need the first breadcumbs format.
Please advise.
when use Pjax => page not refresh but url is changed
use this code maybe your problem solving
<?php Pjax::begin(['enablePushState' => false]); $form = ActiveForm::begin(['action' => '', 'options' => ['data-pjax' => '']]); ?>

Yii2: What is the correct way to include the grid-view widget in form file

I have this code in my _form.php. The problem I am facing is if I am putting the pagination part below it does work, but filter doesn't work. If I am putting the filter part below the pagination part, the filter part work and pagination doesn't work.
Again my netbeans IDE is complaining that I have declared the $dataprovider twice.
here is my code.
Form part:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\grid\GridView;
use yii\data\ActiveDataProvider;
use app\models\State;
use app\models\StateSearch;
use app\models\City;
/* #var $this yii\web\View */
/* #var $model app\models\State */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="row">
<div class="col-lg-3">
<div class="col-lg-4 col-lg-offset-1">
<div class="state-form">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'state_name')->textInput(['maxlength' => 50]) ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
Pagination part
<?php
$dataProvider = new ActiveDataProvider([
'query' => State::find(),
'pagination' => [
'pageSize' => 5,
],
]);
?>
Filter part
<?php
$searchModel = New StateSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
?>
Gridview Widget
<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
// 'id',
'state_name',
['class' => 'yii\grid\ActionColumn'],
],
]); ?>
</div>
</div>
What is the correct approach that my filter and pagination both works.
How to show action column icons inline(that is horizontally), I can do it at view level by setting the width, but thinking if there is a global setting for that.
Can provide the pagination option on the grid-view for user selection like 5,10 or all.
Thanks.

Yii2 Multiple instances of the same model

I want to get multiplie instance of the same model in my controller. I saw this wiki for Yii 1.1 and tried like that but in my code only last instance in form was acceble from controller my code is here (I commented code with error and variable values):
$model = new Person(['scenario' => 'create_update']);
$contractDate = new DatePart(); // DatePart is my own class
$contractExpirationDate = new DatePart(); // DatePart is my own class
if ($model->load(Yii::$app->request->post()) &&
$contractDate->load(Yii::$app->request->post()) &&
$contractExpirationDate->load(Yii::$app->request->post())){
Yii::info(Yii::$app->request->post(),'test'); // only one instance of Person and one instance of DatePart are available here
Yii::info($_POST['DatePart'],'test'); // only last instance of DatePart (contractExpirationDate in html form) is available here
Yii::info($_POST['DatePart'][0],'test'); // Error: Undefined offset: 0
Yii::info($_POST['DatePart'][1],'test'); // Error: Undefined offset: 1
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('create', [
'model' => $model,
'contractDate' => $contractDate,
'contractExpirationDate' => $contractExpirationDate,
]);
}
It is my form view in _form.php:
<?php
use yii\helpers\Html;
//use yii\widgets\ActiveForm;
use kartik\widgets\ActiveForm;
use common\models\DataOperations;
/* #var $this yii\web\View */
/* #var $model app\models\Person */
/* #var $contractDate backend\viewModels\DatePart */
/* #var $contractExpirationDate backend\viewModels\DatePart */
/* #var $form yii\widgets\ActiveForm */
?>
<div class="user-form">
<?php
$form = kartik\widgets\ActiveForm::begin(
[
'id' => $model->isNewRecord ? 'user-form-create' : 'user-form-update',
'type' => ActiveForm::TYPE_VERTICAL,
//'enableAjaxValidation' => true,
'fieldConfig' => [
//'autoPlaceholder'=>true
]
]);
?>
<?= $form->field($model, 'name')->textInput(['maxlength' => 60]) ?>
<?= $form->field($model, 'family')->textInput(['maxlength' => 60]) ?>
<?= $form->field($model, 'mobile')->textInput() ?>
<?= $form->field($contractDate, 'year')->textInput() ?>
<?= $form->field($contractDate, 'month')->textInput() ?>
<?= $form->field($contractDate, 'day')->textInput() ?>
<?= $form->field($contractExpirationDate, 'year')->textInput() ?>
<?= $form->field($contractExpirationDate, 'month')->textInput() ?>
<?= $form->field($contractExpirationDate, 'day')->textInput() ?>
<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(); ?>
</div>
It is log result for:
Yii::info(Yii::$app->request->post(),'test')
in debugger as you seen only last DatePart available but I have two DatePart model instance (contractDate and contractExpirationDate):
[
'_csrf' => 'Vl81R0ZvMk1hD1oELT9aDzkIe3EPHFgiIBJTBhA9RD8GbFM.AhlVBw==',
'Person' => [
'name' => 'test name',
'family' => 'test family',
'mobile' => '09121212123',
],
'DatePart' => [
'year' => '2015',
'month' => 'Jun',
'day' => 'Mon',
],
]
Controller:
$model = new Person(['scenario' => 'create_update']);
$dates = [
'contractDate' => new DatePart(),
'contractExpirationDate' => new DatePart()
];
if ($model->load(Yii::$app->request->post())) {
if (Model::loadMultiple($dates, Yii::$app->request->post()) && Model::validateMultiple($dates)) {
foreach ($dates as $date) {
$date->save();
}
// or
$contractDate = $dates['contractDate'];
$contractExpirationDate = $dates['contractExpirationDate'];
// ...... some logic
$model->save();
return $this->redirect(['view', 'id' => $model->id]);
}
}
else {
return $this->render('create', [
'model' => $model,
'dates' => $dates
]);
}
View Form:
<?= $form->field($dates, '[contractDate]year')->textInput() ?>
<?= $form->field($dates, '[contractDate]month')->textInput() ?>
<?= $form->field($dates, '[contractDate]day')->textInput() ?>
<?= $form->field($dates, '[contractExpirationDate]year')->textInput() ?>
<?= $form->field($dates, '[contractExpirationDate]month')->textInput() ?>
<?= $form->field($dates, '[contractExpirationDate]day')->textInput() ?>
To complement b24 answer.
// In View Form add foreach:
<?php foreach ($dates as $index => $date): ?>
<?= $form->field($date, '[contractDate]year')->textInput() ?>
<?= $form->field($date, '[contractDate]month')->textInput() ?>
<?= $form->field($date, '[contractDate]day')->textInput() ?>
<?= $form->field($date, '[contractExpirationDate]year')->textInput() ?>
<?= $form->field($date, '[contractExpirationDate]month')->textInput() ?>
<?= $form->field($date, '[contractExpirationDate]day')->textInput() ?>
<?php endforeach; ?>
// - or - add index
<?= $form->field($dates['contractDate'], '[contractDate]year')->textInput() ?>
<?= $form->field($dates['contractDate'], '[contractDate]month')->textInput() ?>
<?= $form->field($dates['contractDate'], '[contractDate]day')->textInput() ?>
<?= $form->field($dates['contractExpirationDate'], '[contractExpirationDate]year')->textInput() ?>
<?= $form->field($dates['contractExpirationDate'], '[contractExpirationDate]month')->textInput() ?>
<?= $form->field($dates['contractExpirationDate'], '[contractExpirationDate]day')->textInput() ?>
This can be is solution for this problem :
http://www.yiiframework.com/forum/index.php/topic/53935-solved-subforms/page__p__248184#entry248184

Categories