Yii2 submit modal form with ajax - yii2

I've success create modal form, but I can't submit it with ajax. Everytime i click submit button it not stay in the index page but instead show echo 1 from my Controller.
My controller
public function actionCreate()
{
$model = new Testing();
if ($model->load(Yii::$app->request->post())) {
if($model->save()){
echo 1;
}else{
echo 0;
}
}else{
return $this->renderAjax('create', [
'model' => $model,
]);
}
}
My form
<div class="testing-form">
<?php $form = ActiveForm::begin(['id' => $model->formName()]); ?>
<?= $form->field($model, 'test')->textInput(['maxlength' => true]) ?>
<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
<?php
$this->registerJS("
$('form#{$model->formName()}'.on('beforeSubmit', function(e)
{
var \$form = $(this);
$.post(
\$form.attr('action'),
\$form.serialize()
)
.done(function(result) {
if(result == 1)
{
$(\$form).trigger('reset');
$.pjax.reload({container:'#issuehrGrid'});
}else
{
$('#message').html(result.message);
}
}).fail(function()
{
console.log('server error');
})
return false;
});"
);
?>
My view
<div class="report">
<h3>HR Issues</h3>
<?= Html::a('<span class="glyphicon glyphicon-plus"></span> Add', ['create'], ['class' => 'btn btn-success modalButton']) ?>
<?php Pjax::begin(['id'=>'issuehrGrid']); ?>
<table class="table table-bordered table-hover">
<tbody>
<?php foreach ($dataProvider->models as $hr) {
?>
<tr>
<td><?=$hr->test;?></td>
</tr>
<?php } ?>
</tbody>
</table>
<?php Pjax::end(); ?>
</div>
Please help me with this.
Thank you!

What I suspect is that it would be showing you the blank page with 1 displayed in it is because after the first submission your Pjax grid is reloaded via the statement
$.pjax.reload({container:'#issuehrGrid'});
and once reloaded your beforeSubmit event is not bound again to the form as the form Html is reloaded again and when you submit the form second time it just makes a simple form submit and displays the blank page with 1, you need to use the pjax:complete event for the pjax, so that one the grid is reloaded your script binds the beforeSubmit event to the form again.
Also, you have a syntax error in your script which should be fixed. Change your script to the following
<?php
$formName = $model->formName();
$js = <<<JS
$(document).on("ready pjax:complete",function(){
$('form#{$formName}').on('beforeSubmit', function(e){
var \$form = $(this);
$.post(
\$form.attr('action'),
\$form.serialize()
).done(function(result) {
if(result == 1)
{
$(\$form).trigger('reset');
$.pjax.reload({container:'#issuehrGrid'});
}else
{
$('#message').html(result.message);
}
}).fail(function()
{
console.log('server error');
})
return false;
});
});
JS;
$this->registerJS(
$js,
\yii\web\View::POS_READY
);
?>
UPDATE
and dont forget to change the controller action code and change the echo 1 to return 1 and echo 0 to return 0

Related

yii2 boostrap 5 and modal

Edit:
I discovered that if i do a clean install, the modal works, and it's after adding hail812/yii2-adminlte3 that the modal system won't work anymore... but i don't find what create this,
original:
little question, does any of you use yii/boostrap5/modal and succeed to render ajax form in a modal ? Because my code used with the older bootstrap won't work.. and i don't find how the new yii/bootstrap5/modal works...
here is my code
<?php
yii\bootstrap5\Modal::begin([
'id' => 'modal',
'size' => 'modal-lg',
//keeps from closing modal with esc key or by clicking out of the modal.
// user must click cancel or X to close
'clientOptions' => ['backdrop' => 'static', 'keyboard' => TRUE]
]);
echo '<div id="modalContent"></div>';
yii\bootstrap5\Modal::end();
?>
<?php
$this->registerJs( <<< EOT_JS_CODE
$(function(){
// changed id to class
$('.modalButton').click(function (e){
e.preventDefault();
$.get($(this).attr('href'), function(data) {
$('#modal').modal('show').find('#modalContent').html(data)
});
document.getElementById('modalHeader').innerHTML = '<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button><h4>' + $(this).attr('title') + '</h4>';
return false;
});
});
EOT_JS_CODE
);
?>
the link i use to open the modal:
<?= Html::a(Yii::t('app', 'Ajouter'), ['create-categorie'], ['class' => 'btn btn-success modalButton','title'=>'Nouvelle catégorie']) ?>
And my code in my controller
public function actionCreateCategorie()
{
$model = new Categorie();
if ($model->load(Yii::$app->request->post())) {
$model->created_at = strtotime('now');
$model->updated_at = strtotime('now');
if( $model->save()){
return 'success';
}else{
return 'error';
}
}
return $this->renderAjax('create-categorie', [
'model' => $model,
],false, true);
}
my console with a strange error i don't get

Yii2 render view as modal, Pop up Window for forms

Render view page as a modal for preview:
<h1><?= Html::encode($this->title) ?></h1>
<p>
<?= Html::button('Create Branches', ['value'=>Url::to(['/branches/create']),'class' => 'btn btn-success','id'=> 'modalButton']) ?>
</p>
<?php
Modal::begin([
'header'=>'<h4>Branches</h4>',
'id'=>'modal',
'size'=>'modal-lg',
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
My controller:
public function actionCreate()
{
return $this->renderAjax('create', [
'model' => $model,
]);
}
My script:
$(function () {
$('#modalButton').click(function () {
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));
});
});
But when I click the link it open a viewpage with no CSS, not a pop-up modal. Please help me with this. Thank you
You can update your code as this.
<h1><?= Html::encode($this->title) ?></h1>
<p>
<!-- updated id to class here -->
<a class="modalButton btn btn-success" href="<?=Url::to(['/branches/create']) ?>">
</p>
<?php
Modal::begin([
'header'=>'<h4>Branches</h4>',
'id'=>'modal',
'size'=>'modal-lg',
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
Update Jquery event.
$(function(){
// changed id to class
$('.modalButton').on('click', function (){
$.get($(this).attr('href'), function(data) {
$('#modal').modal('show').find('#modalContent').html(data)
});
return false;
});
});

Yii2 render view as modal

I want to render view page as a modal for preview
<div>
<?php foreach($softs as $soft) { ?>
<a id="modalButton" href="<?=Url::to(['documents/view', 'id'=>$soft->id]); ?>"><h3><?=$soft->title; ?></h3></a>
<?php
Modal::begin([
'header' => 'Test',
'id' => 'modal',
'size' => 'modal-lg',
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
<?php } ?>
</div>
My controller
public function actionIndex()
{
$query = Documents::find();
$softs = $query->where(['type_id' => 2])->all();
return $this->render('index', [
'softs' => $softs,
]);
}
public function actionView($id)
{
return $this->renderAjax('view', [
'model' => $this->findModel($id),
]);
}
My script
$(function(){
$('#modalButton').click(function (){
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('href'));
});
});
But when I click the link it open a viewpage with no CSS, not a pop-up modal.
Please help me with this. Thank you
You update your code as per below.
<div>
<?php foreach($softs as $soft) { ?>
<!-- updated id to class here -->
<a class="modalButton" href="<?=Url::to(['documents/view', 'id'=>$soft->id]); ?>"><h3><?=$soft->title; ?></h3></a>
<?php } ?>
<!-- We don't need to print modal popup multiple times -->
<?php
Modal::begin([
'header' => 'Test',
'id' => 'modal',
'size' => 'modal-lg',
]);
echo "<div id='modalContent'></div>";
Modal::end();
?>
</div>
Update click event.
$(function(){
// changed id to class
$('.modalButton').click(function (){
$.get($(this).attr('href'), function(data) {
$('#modal').modal('show').find('#modalContent').html(data)
});
return false;
});
});

yii2: js calulation in server side

This is a page for calculate the product order.
My mentor told me that:
"The code put the code calculation logic inside JavaScript which means, user can simply inject and modified the content and get discount to make it safe, may either do a recalculation on submit at server side before display, or make the js function to call API, and return the result instead of put calculation logic inside JS"
But I really can't get it, how can I make it in server side?
views:
<?php $form = ActiveForm::begin([
'action'=>['summary'],
'id'=>'order-form',
]); ?>
<?= Html::dropDownList('country', null,['malaysia'=>'Malaysia','singapore'=>'Singapore', 'brunei'=>'Brunei'],['id'=>'country']) ?>
<?= Html::textInput('code','',['class'=>'form-control','placeholder'=>'promotion code','id'=>'code', 'style'=>'text-transform:uppercase'])?>
<?= Html::button('Apply', ['class' => 'btn btn-primary', 'id'=>'apply']) ?>
<?= Html::hiddenInput('id', $model->id) ?>
<?= Html::hiddenInput('discount', '', ['id'=>'discount']) ?>
<?= Html::hiddenInput('ship','',['id'=>'ship']) ?>
<?= Html::hiddenInput('qty', $qty, ['id'=>'qty']) ?>
<?= Html::hiddenInput('subtotal', $subtotal, ['id'=>'subtotal']) ?>
<?= Html::submitButton('Checkout', ['class' => 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
js:
$(document).ready(function() {
var qty=$('#qty').val();
var subtotal=$('#subtotal').val();
$('#discount').val(0);
$("#apply").click(function() {
var code=$('#code').val().toUpperCase();
var off5=(subtotal*0.05).toFixed(2);
var off15=15;
if(code=='OFF5PC'){
if (qty>=2)
$('#discount').val(off5);
else{
$('#discount').val(0);
alert('At least 2 quantities');
}
}
else if(code=='GIVEME15'){
if(subtotal>=100)
$('#discount').val(off15);
else{
$('#discount').val(0);
alert('Minumum puchase of RM100');
}
}
else{
$('#discount').val(0);
alert('Invalid promotion code');
}
if ($('#discount').val()=='0'){
$('#code').val('');
}
});
if(qty>=2||subtotal>=150){
$('#ship').val(0);
$('#shipping').html('0');
}
else{
$('#ship').val(10);
$('#shipping').html('10');
}
$("#country").change(function() {
var country=$('#country').val();
if(country=='malaysia'){
if(qty>=2||subtotal>=150){
$('#ship').val(0);
$('#shipping').html('0');
}
else{
$('#ship').val(10);
$('#shipping').html('10');
}
}
else if(country=='singapore'){
if(subtotal>=300){
$('#ship').val(0);
$('#shipping').html('0');
}
else{
$('#ship').val(20);
$('#shipping').html('20');
}
}
else if(country=='brunei') {
if(subtotal>=300){
$('#ship').val(0);
$('#shipping').html('0');
}
else{
$('#ship').val(25);
$('#shipping').html('25');
}
}
});
});
controllers:
public function actionSummary()
{
$id=Yii::$app->request->post('id');
$qty=Yii::$app->request->post('qty');
$discount=Yii::$app->request->post('discount');
$shipping=Yii::$app->request->post('ship');
$subtotal=Yii::$app->request->post('subtotal');
$area=Yii::$app->request->post('country');
$code=Yii::$app->request->post('code');
$summary=Products::findOne($id);
return $this->render('summary', [
'model' => $summary,
'quantity'=>$qty,
'discount'=>$discount,
'shipping'=>$shipping,
'subtotal'=>$subtotal,
'area'=>$area,
'code'=>$code,
]);
}
use browser tools inspect to determine your id of each fields. Usually the default id in Yii2 begins with view_name combine with "-" and field name.
For validating the form onsubmit, you can enable ajaxvalidation in your form like below.
View:
<?php $form = ActiveForm::begin([
'action'=>['summary'],
'enableAjaxValidation' => true,
'id'=>'order-form',
]); ?>
<?= $form->field($model, 'country')->dropDownList(['malaysia'=>'Malaysia','singapore'=>'Singapore', 'brunei'=>'Brunei']) ?>
<?= $form->field($model, 'code', ['options' => ['class' => 'form-control', 'id'=>'code']])->textInput(['placeholder'=>'promotion code'])?>
<?= Html::button('Apply', ['class' => 'btn btn-primary', 'id'=>'apply']) ?>
<?= Html::hiddenInput('id', $model->id) ?>
<?= Html::hiddenInput('discount', '', ['id'=>'discount']) ?>
<?= Html::hiddenInput('ship','',['id'=>'ship']) ?>
<?= Html::hiddenInput('qty', $qty, ['id'=>'qty']) ?>
<?= Html::hiddenInput('subtotal', $subtotal, ['id'=>'subtotal']) ?>
<?= Html::submitButton('Checkout', ['class' => 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
In your controller file, please add the ajax validation code in your controller before inserting into database. Below is the example ajax validation code for validating from server side.
Controller:
public function actionYourActionName(){
$model = new YourModelClass();
if ($model->load(Yii::$app->request->post())) {
if (Yii::$app->request->isAjax) {
Yii::$app->response->format = yii\web\Response::FORMAT_JSON;
return ActiveForm::validate($model);
}
if($model->save())){
//after successful save if you want to do any thing those codes will goes here.
}
}
return $this->render('your-view-file-name', ['model' => $model]);
}
Model:
<?php
namespace app\models;
use yii;
use yii\db\ActiveRecord;
class YourModelClass extends ActiveRecord
{
...
public function rules(){
return [
[['id', 'discount', 'ship', 'qty', 'subtotal'], 'safe'],
[['country', 'code'], 'required']
];
...
}
?>

check a specific submit button value in controller (Yii2)

how to check a submit button value in controller (Yii2). I am working with multiple submit button.
I tried simple php code. but it is not working.
if(isset($_POST['next']) && $_POST['next']=='gotocartfive')
code in view is :
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'status')->checkbox(); ?>
</div>
<div class="form-group">
<?php echo Html::submitButton('NEXT',array('value'=>'gotocartfive','name' => 'next','id'=>'next_summary','class'=>'btn btn-primary pull-right')); ?>
<?php echo Html::submitButton('PREVIOUS',array('value'=>'previous_four','name' => 'cartfour','class'=>'btn btn-primary pull-left')); ?>
</div>
<?php ActiveForm::end(); ?>
<?= Html::submitButton('Submit 1', ['name' => 'action', 'value' => 'submit_1']) ?>
<?= Html::submitButton('Submit 2', ['name' => 'action', 'value' => 'submit_2']) ?>
PHP
If (\Yii::$app->request->isPost) {
switch (\Yii::$app->request->post('action')) {
case 'submit_1':
case 'submit_2':
}
}
When you submit form by pressing enter (without click any submit button), submit_1 will be default value.
You can try following code.
Code in view file.
<?= Html::submitButton(Yii::t('app', '<i class="fa fa-times"></i> Remove'), ['class' => 'btn red', 'name' => 'submit', 'value' => '0']) ?>
<?= Html::submitButton(Yii::t('app', '<i class="fa fa-check"></i> Save'), ['class' => 'btn blue', 'name' => 'submit', 'value' => '1']) ?>
Code in controller action
if (Yii::$app->request->post()) {
if (Yii::$app->request->post('submit') == 0) {
//Code for value 0
}
if (Yii::$app->request->post('submit') == 1) {
//Code for value 1
}
}
Please let me know if you've any questions.
Try This :
View File
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'status')->checkbox(); ?>
<div class="form-group">
<?= Html::submitButton('NEXT',[ 'name'=>'submit', 'value' => 'next', 'class' => 'btn btn-primary pull-right']) ?>
<?= Html::submitButton('PREVIOUS',[ 'name'=>'submit', 'value' => 'previous', 'class' => 'btn btn-primary pull-right') ?>
</div>
<?php ActiveForm::end(); ?>
Controller File
public function actionYourControllerName()
{
if(isset($_POST['submit') && $_POST['submit']=='next')
{
// your code
}
else if(isset($_POST['submit']) && $_POST['submit']=='previous')
{
// your code
}
}
Also you can add this little js snippet to your project and bind it to beforeSubmit event in yii.activeForm.js like this:
(function ($) {
var formId = !!yiiconfig.viewPolicyParams && yiiconfig.viewPolicyParams.formId && yiiconfig.viewPolicyParams.formId,
$form = formId && $("#" + formId);
/**
* Updates hidden field that represents clicked submit button.
* #param event event object triggered
*/
function updateHiddenButton (event) {
var $buttons = $form.find(':submit');
$buttons.length && $buttons.each(function (i,b) {
var $hiddenButton = $('input[type="hidden"][name="' + $(b).attr('name') + '"]', $form);
$hiddenButton.length && $hiddenButton.remove();
});
};
$form && $form.bind('beforeSubmit.' + formId, updateHiddenButton);
} (jQuery));
This code removes all hidden inputs which are being created by yii.activeForm before submitting.
Then after this inputs will be recreated by yii.activeForm.
hope this helps