Pjax Request is executed 2 times one aborted and then execute - yii2

I am facing a problem with PJAX. When Submitting ActiveForm through Pjax ,action is executing Twice .
One is aborted and another is success.
Meanwhile there is 2 new models inserted in database since former is doing insertion and aborted.
My Controller code is
public function actionCreate()
{
$model = new Products();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return "Success";
} else {
return $this->renderAjax('_form', [
'model' => $model,
]);
}
}
and my _form.php is
<?php
$this->registerJs('
$.pjax.defaults.timeout = 5000;
$("#product-form-pjax").on("pjax:success", function(data, status, xhr, options) {
if(options.responseText == "Success"){
$.pjax.reload({container: "#pjax-gridview", timeout: 2000});
$("#activity-modal").modal("hide");
}
});
');
?>
<div class="products-form">
<?php Pjax::begin(['id' => 'product-form-pjax', 'enablePushState' => FALSE]) ?>
<?php $form = ActiveForm::begin([
'id' => 'crud-model-form',
'action' => ['product/create'],
'options' => [
'data-pjax' => true,
]
]);
?>
<?= $form->field($model, 'name') ?>
<?= $form->field($model, 'image') ?>
<?= $form->field($model, 'brand')->dropDownList(ArrayHelper::map(Brands::find()->all(),'id','name')) ?>
<?= $form->field($model, 'category')->dropDownList(ArrayHelper::map(Categories::find()->all(),'id','name'),['select' => ''])?>
<?= $form->field($model, 'lot') ?>
<?= $form->field($model, 'prize') ?>
<?= $form->field($model, 'condition') ?>
<?= $form->field($model, 'extra_condition') ?>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
<?php Pjax::end() ?>
</div>
I am creating this model through bootstrap model with Pjax enabled on GridView
So why my action is aborted and then execute.
I have already changes PJAX timeout option in it

I'm not 100% sure on this, as I would need to test your code directly to make sure this works. But I think the pjax:success event gets fired twice. I remember looking into it a while back and it seemed it was intended behavior for the success event to fire twice.
When I try to do something similar to what you are doing, I've used pjax:end instead of pjax:success. So you may want to try that and see if it helps.
Additionally, it may help to make sure your javascript is being called once the document is ready. So updating your script as below may also help. You can learn more about customizing where scripts are added in the Yii2 Docs http://www.yiiframework.com/doc-2.0/guide-output-client-scripts.html
$this->registerJs('
$.pjax.defaults.timeout = 5000;
$("#product-form-pjax").on("pjax:end", function(data, status, xhr, options) {
if(options.responseText == "Success"){
$.pjax.reload({container: "#pjax-gridview", timeout: 2000});
$("#activity-modal").modal("hide");
}
});
', $this::POS_READY);

I had this poblem, it is just a timeout problem. The default timeout of Pjax is too short.

Related

yii2 - two modal in one active form

I have 2 modals in one active form. Let's say first one is modal-ticket and second one is contract-ticket. First time, I click button to show modal-ticket, and it was fine, but when I click button to show modal-contract, it also call script modal-ticket or otherwise. why?
this is my code.
<?php $form = ActiveForm::begin(); ?>
<div id="BtnSearchTicket">
<?= Html::button('Search Ticket', [
'value' => Url::to('../ticket-timbangan/list'),
'class' => 'btn btn-primary',
'id' => 'BtnModalTicketList',
'data-toggle'=>"modal",
'data-target'=>"#modalTicketList",
]) ?>
</div>
<div id="BtnSearchContract">
<?= Html::button('Search Contract', [
'value' => Url::to('../contract/list'),
'class' => 'btn btn-primary',
'id' => 'BtnModalContractList',
'data-toggle'=>"modal",
'data-target'=>"#modalContractList",
]) ?>
</div>
<?php ActiveForm::end(); ?>
<?php
Modal::begin([
'header' => 'Ticket List',
'id' => 'modalTicketList',
'size' => 'modal-lg',
'class' => 'style=width:auto'
]);
echo "<div id='modalContentTicket'></div>";
Modal::end();
?>
<?php
Modal::begin([
'header' => 'Contract List',
'id' => 'modalContractList',
'size' => 'modal-lg',
'class' => 'style=width:auto'
]);
echo "<div id='modalContentContract'></div>";
Modal::end();
?>
<?php
$script = <<< JS
$('#BtnModalTicketList').click(function(e){
e.preventDefault();
$('#modalTicketList').modal('show')
.find('#modalContentTicket')
.load($(this).attr('value'));
return false;
});
$('#BtnModalContractList').click(function(e){
e.preventDefault();
$('#modalContractList').modal('show')
.find('#modalContentContract')
.load($(this).attr('value'));
return false;
});
JS;
$this->registerJs($script);
?>
this are the error found in console web browser
GET http://localhost/pks/web/ticket-timbangan/get-ticket?id=1 404 (Not Found)
GET http://localhost/pks/web/contract/get-contract?id=2 404 (Not Found)
please help.
Try This: using one modal on your form:
<?php $form = ActiveForm::begin(); ?>
<div id="BtnSearchTicket">
<?= Html::button('Search Ticket', [
'value' => Url::to('../ticket-timbangan/list'),
'class' => 'btn btn-primary showModal',
'id' => 'BtnModalTicketList',
'title' => 'Search Ticket',
]) ?>
</div>
<div id="BtnSearchContract">
<?= Html::button('Search Contract', [
'value' => Url::to('../contract/list'),
'class' => 'btn btn-primary showModal',
'title' => 'Search Contract',
'id' => 'BtnModalContractList',
]) ?>
</div>
<?php ActiveForm::end(); ?>
<?php
Modal::begin([
'headerOptions' => ['id' => 'modalHeader'],
'id' => 'modal',
'size' => 'modal-lg',
'closeButton' => [
'id'=>'close-button',
'class'=>'close',
'data-dismiss' =>'modal',
],
'class' => 'style=width:auto',
'clientOptions' => [
'backdrop' => false, 'keyboard' => true
]
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
<?php
$script = <<< JS
$(document).on('click', '.showModal', function(){
if ($('#modal').hasClass('in')) {
$('#modal').find('#modalContent')
.load($(this).attr('value'));
document.getElementById('modalHeader').innerHTML = '<h4>' + $(this).attr('title') + '</h4>';
} else {
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));
document.getElementById('modalHeader').innerHTML = '<h4>' + $(this).attr('title') + '</h4>';
}
});
JS;
$this->registerJs($script);
?>
From viewing your code what calls my attention is how you use the Url::to() function. Not sure why you use ../. I have fiddled with using more than one modal in a form and the code is similar to what your are doing. I suggest you try changing your Url::to() function as follows:
Url::to('/ticket-timbangan/list')
and
Url::to('/contract/list')
Another suggestion would be to try with
Yii::$app->urlManager->createUrl('/ticket-timbangan/list')
and
Yii::$app->urlManager->createUrl('/contract/list')
Let me know if this helps.
First, many thanks to kalu who has helped me 2 days to solve my problem. Two modals which contains grid need to define different classes to prevent execute previous script.
'value' => Url::to('../ticket-timbangan/list') and 'value' => Url::to('../contract/list'), both has two gridview and same select-row class. This class is root cause of the problem, because it's same class and execute both script.
Thanks Kalu, you save my day.

Yii2 get value from view file to controller

In controller file i print this,
in controller am getting NULL after printing.
how to the know if button is clicked ?
var_dump(\Yii::$app->request->post('submit'));
In view file
<?php $form = ActiveForm::begin([
'id' => 'button',
]); ?>
<?= Html::submitButton('submit', ['name' => 'submit', 'value' => 'submit_1', 'class' => 'btn']) ?>
<?php ActiveForm::end(); ?>

Yii2 - checkbox change commit ActiveForm

in the index.php there is a checkbox within a active form
<div class="form-group pull-right" style="margin-right: 10px">
<?php Pjax::begin(['id' => 'options']); ?>
<?php $form = ActiveForm::begin(['method' => 'get', 'action' => ['ensemble/index'], 'options' => ['data-pjax' => true]]); ?>
<?= $form->field($searchModel, 'completed')->checkbox(); ?>
<?= Html::submitButton('Apply', ['class' => 'btn btn-success']) ?>
<?php ActiveForm::end(); ?>
<?php Pjax::end(); ?>
</div>
also there is kartik gridview in the index.php
<?= GridView::widget($gridConfig); ?>
with the following configuration
$gridConfig['pjax'] = true;
$gridConfig['pjaxSettings'] = ['options' => ['id' => 'pjaxGrid']];
the ensemble controller with the index action looks like this
public function actionIndex()
{
$searchModel = new EnsembleSearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
This does work every thing just fine. I can check / uncheck the checkbox field and hit the submit button; which then reloads the gridview. Just cool.
Now i was wondering if it is possible, to just make this with only by clicking the checkbox? So if i check / uncheck the checkbox the gridview will be reloaded (pjax'd).
cheers,
Luc
Assign id to your form as well as class to your checkbox.
<div class="form-group pull-right" style="margin-right: 10px">
<?php Pjax::begin(['id' => 'options']); ?>
<?php $form = ActiveForm::begin([
'id' => 'filter-form',
'method' => 'get',
'action' => ['ensemble/index'],
'options' => ['data-pjax' => true]
]); ?>
<?= $form->field($searchModel, 'completed',['class'=>'status_chk'])->checkbox(); ?>
<?= Html::submitButton('Apply', ['class' => 'btn btn-success']) ?>
<?php ActiveForm::end(); ?>
<?php Pjax::end(); ?>
</div>
Add this script to your index.php file.
<?php
$this->registerJs(
'$("document").ready(function(){
$(document).on("change",".status_chk", function() {
$("#filter-form").submit();
});
});'
);
?>
I would say that you could do that with JavaScript. You could do something like this:
You must know how to identify the Form and the Checkbox (you could assign them so ids..)
In a JavaScript you could do something like this:
var form = document.getElementById("form-id");
document.getElementById("your-checkbox-id").addEventListener("click", function () {
form.submit();
});
As explain in this answer:
submit form with javaScript

YII2 how to use pjax to submit a form without refresh the page

I use a yii2 to create a website, trying to use a form to submit some data.
Can some body give me a example. Tell me how to use pjax to submit a form without reload the page.
There's an example of Yii2 Pjax submit form in this link
views\site\form-submission.php:
<?php Pjax::begin(); ?>
<?= Html::beginForm(['site/form-submission'], 'post', ['data-pjax' => '', 'class' => 'form-inline']); ?>
<?= Html::input('text', 'string', Yii::$app->request->post('string'), ['class' => 'form-control']) ?>
<?= Html::submitButton('Hash String', ['class' => 'btn btn-lg btn-primary', 'name' => 'hash-button']) ?>
<?= Html::endForm() ?>
<h3><?= $stringHash ?></h3>
<?php Pjax::end(); ?>
controllers\SiteController.php:
public function actionFormSubmission()
{
$security = new Security();
$string = Yii::$app->request->post('string');
$stringHash = '';
if (!is_null($string)) {
$stringHash = $security->generatePasswordHash($string);
}
return $this->render('form-submission', [
'stringHash' => $stringHash,
]);
}

ActiveForm without model yii2

I want to create ActiveForm without model for just in case something. I did try with dynamicModel but i got some error :
use yii\base\DynamicModel;
$model = DynamicModel::validateData(compact('KOMENTAR'), [
[['KOMENTAR'], 'string', 'max' => 128],
]);
This is the form i want to create
<br>
<?php $form = ActiveForm::begin([
'method' => 'post',
]); ?>
<?= $form->field($model, 'KOMENTAR')->textarea(['rows' => 6])->label(false) ?>
<div class="form-group">
<?= Html::submitButton('POST', ['class' => 'btn btn-primary']) ?>
</div>
This is the error
Getting unknown property: yii\base\DynamicModel::KOMENTAR
Normally ActiveItems are used to work with a model, but Yii2 have a helper class called Html to use the same items like classic HTML.
Use beginForm() method from Html. And try something like that:
use yii\helpers\Html;
<?= Html::beginForm(['/controller/view', 'id' => $model->id], 'POST'); ?>
<?= Html::textarea('KOMENTAR', '', ['rows' => 6])->label(false); ?>
<div class="form-group">
<?= Html::submitButton('POST', ['class' => 'btn btn-primary']); ?>
</div>
<?= Html::endForm(); ?>
You can read more about this helper in the documentation.
Since you are using compact('KOMENTAR'), you should have a $KOMENTAR variable.
Read more about compact : http://php.net/manual/fr/function.compact.php
Or you should simply create your model like this :
$model = new \yii\base\DynamicModel(['KOMENTAR']);
$model->addRule(['KOMENTAR'], 'string', ['max' => 128]);
if ($model->load(Yii::$app->request->post()) && $model->validate()) {
// do what you want
}