check a specific submit button value in controller (Yii2) - 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

Related

Modal Form not work in Yii2 with AdminLTE

I built a web app using Yii2 with adminLTE theme. i'm trying to make modal form in my web app, I've tried in Yii2 without adminLTE it work fine like this:
I did the same way in Yii2 with adminLTE it failed, when I clicked the button, it didn't do anything, and I tried to do inspectElement and I got this:
This is my view in index.php:
<?php
use yii\helpers\Html;
use kartik\detail\DetailView;
use kartik\grid\GridView;
use yii\helpers\Url;
use yii\bootstrap\Modal;
/* #var $this yii\web\View */
/* #var $modelTrip backend\models\TripsSchedule */
\yii\web\YiiAsset::register($this);
?>
<p>
<?= Html::button('Add Schedule', ['value' => Url::to('/intra/admin/bus-passengers/create'), 'class' => 'btn btn-success', 'id' => 'modalButton']) ?>
</p>
<?php
Modal::begin([
'header' => '<h4>Add Passenger</h4>',
'id' => 'modal',
'size' => 'modal-lg',
]);
echo "<div id='modalContent'><div>";
Modal::end();
?>
<div>
<?=
DetailView::widget([
'model' => $modelTrip,
'id' => $modelTrip->tripScheduleId,
'responsive' => true,
'enableEditMode' => false,
'condensed' => true,
'hover' => true,
'mode' => DetailView::MODE_VIEW,
'mainTemplate' => '{detail}',
'attributes' => [
[
'attribute' => 'departureTime',
'label' => 'Departure Time',
'value' => function ($form, $widget) {
$model = $widget->model;
return date('H:i', strtotime($model->departureTime)) . ' WIB';
},
],
],
])
?>
</div>
This is code in controller:
public function actionCreate()
{
$model = new BusPassengers();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
return $this->redirect(['view', 'id' => $model->busPassengerId]);
}
return $this->renderAjax('create', [
'model' => $model,
]);
}
You can see, it didn't render anything. Do I need add another additional code because I'm using adminLTE?
Update
Here is the js:
$(function () {
$('#modalButton').click(function () {
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));
});
});
Update
Here is the view source and console screenshot
This line is not needed if you already have a layout file, so please remove this
\yii\web\YiiAsset::register($this);
also please make sure jquery file loaded before your js code else it will not work since bootstrap modal is depend on jQuery (please check your console).
Or at the end, your can add js code as Yii way:
<?php
$script = <<< JS
$('#modalButton').click(function () {
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));
});
JS;
$this->registerJs($script);
?>
Let me know if it work or please post screenshot of viewSource and console.
Thank you
Update
Try replace these code block and it will work:
1. JS
<script type="text/javascript">
function showModal() {
$('#passenger_modal').modal('show');
$('#passenger_modal_content').load("<?=Yii::getAlias('#web')?>/intra/admin/bus-passengers/create");
}
</script>
2. BUTTON
<p>
<?= Html::button('Add Schedule', ['class' => 'btn btn-success', 'onClick'=>'showModal()']) ?>
</p>
3. MODAL BLOCK
<?php
Modal::begin([
'header' => '<h4>Add Passenger</h4>',
'id' => 'passenger_modal',
'size' => 'modal-lg',
]);
echo '<div id="passenger_modal_content"><div>';
Modal::end();
?>
I just change the id's of blocks but that is not matter at all.
this updated version worked for me problem was my layout footer was hidden and being shown with modal body with this question solution
Yii2 and adminlte : 2.4.13
<?php
Modal::begin([
'header' => '<h4><i class="fa fa-book" style="padding-right:5px"></i>' .
$model->name
. '</h3>',
'id' => 'modal',
'size' => 'modal-lg',
]);
?>
<?= "<div id='modalContent'>" ?>
<?php
$form = ActiveForm::begin(); ?>
<div class="box box-info">
<div class="box-body">
<div class="form-group">
<?= $form->field($chapter, 'name')->textInput() ?>
</div>
<div class="form-group">
<?= $form->field($chapter, 'book_id')->hiddenInput(['value' => $model->id])->label(false); ?>
</div>
<div class="form-group">
<?= $form->field($chapter, 'description')->textarea(['rows' => '6']) ?>
</div>
</div>
<div class="box-footer">
<?= Html::a('Cancel', ['index'], ['class' => 'btn btn-default']) ?>
<?= Html::submitButton('Save', ['class' => 'btn btn-info pull-right']) ?>
</div>
</div>
<?php ActiveForm::end();
Modal::end();
?>
" ?>
<script>
$(function() {
$('#modalButton').click(function() {
$('#modal').modal('show')
.find('#modalContent')
.load($(this).attr('value'));
});
});
</script>

Yii2 update a record based on form in a view file

I tried to update one field of record based on value in a form. The form are placed within a modal in a view file.
view
Modal::begin([
'header' => '<h3>Update Payment Reference</h3>',
'toggleButton' => ['label' => 'Pay','class' => 'btn btn-success'],
]); ?>
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'pcpayreference')->textInput(['maxlength' => true]) ?>
<?= Html::submitButton('Update', ['class' => 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
<?php Modal::end();
But I have no idea how to pass those value to my controller so it can update whatever the user have input and submitted.
Controller
public function actionPay($id)
{
$model = Purchase::findOne($id);
if ($model->load(Yii::$app->request->post()) && $model->save()) {
$model->pcstatus = 'Paid';
$model->pcpaydate = date('Y-m-d H:i:s');
$model->save();
return $this->redirect(['view', 'id' => $model->pcid]);
}
}
I'm new to Yii framework. Any help is much appreciated.
EDIT
The only thing I want to do is to update only this field (current record/view) into database instead of update the whole field.
You must set action in your form with id, it will work
Modal::begin([
'header' => '<h3>Update Payment Reference</h3>',
'toggleButton' => ['label' => 'Pay','class' => 'btn btn-success'],
]); ?>
<?php $form = ActiveForm::begin([
'action' => ['controller/pay','id'=>$id],
]); ?>
<?= $form->field($model, 'pcpayreference')->textInput(['maxlength' => true]) ?>
<?= Html::submitButton('Update', ['class' => 'btn btn-primary']) ?>
<?php ActiveForm::end(); ?>
<?php Modal::end();
I think this is the problem regarding csrf validation, just make sure in your config about enableCsrfValidation :
just put this function in your controller
public function beforeAction($action) {
$this->enableCsrfValidation = false;
return parent::beforeAction($action);
}
Let me know please.

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']
];
...
}
?>

Yii2 different form fields on create and on update scenario

In my Model I have created different scenarios. I have one form which is rendered bu both create and update method. The form fields are as follows
Form.php
<?php $form = ActiveForm::begin(); ?>
<?= $form->errorSummary($model, $options = ['header'=>'', 'class'=>'pull-left errorDiv']); ?>
<?= $form->field($model, 'user_fname')->textInput(['class'=>'form-control']);?>
<?= $form->field($model, 'user_lname')->textInput(['class'=>'form-control']); ?>
<?= $form->field($model,'user_email')->textInput(['class'=>'form-control']); ?>
<?= $form->field($model, 'user_password_hash')->passwordInput([]); ?>
<?= $form->field($model, 'user_password_hash_repeat')->passwordInput(['class'=>'form-control']); ?>
<?php $items = ArrayHelper::map(SimAuthAssignment::find()->all(),'item_name' ,'item_name');?>
<?= $form->field($mode, 'item_name')->dropDownList($items,[]);?>
<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(); ?>
On using update scenario I want only my email, firstname and last name to be rendered from the form.
const SCENARIO_REGISTER = 'signup';
const SCENARIO_CREATE = 'create';
const SCENARIO_UPDATE = 'update';
public function scenarios()
{
return [
self::SCENARIO_REGISTER => ['user_email', 'user_password_hash', 'user_fname', 'user_lname', 'agree','!user_password_hash_repeat','required'],
self::SCENARIO_CREATE => ['user_email', 'user_password_hash', 'user_fname', 'user_lname','!user_password_hash_repeat','required'],
self::SCENARIO_UPDATE => ['user_email', 'user_fname', 'user_lname', 'required'],
];
}
public static function tableName()
{
return 'sim_user';
}
And in my controller update method I am using scenario as below code.
public function actionUpdate($id)
{
$model = $this->findModel($id);
$model->scenario = SimUser::SCENARIO_UPDATE;
// var_dump($model->scenario); exit();
$mode = \app\modules\auth\models\SimAuthAssignment::find()->where(['user_id' => $id])->one();
if ($model->load(Yii::$app->request->post())&& $mode->load(Yii::$app->request->post())) {
$model->save();
return $this->redirect(['view', 'id' => $model->user_id]);
} else {
return $this->renderAjax('update', [
'model' => $model,
'mode' => $mode,
]);
}
}
I want to get only the email, firstname and lastname form fields to be rendered in the form when I edit. I want to ignore the others fields in the form when I edit. What am I missing here? Thanks!!
You are using an activeForm with all the inputField .. so all the fields are submit .. if you want only email, firstname and lastname
you should use another view with onnly these fields
<?php $form = ActiveForm::begin(); ?>
<?= $form->errorSummary($model, $options = ['header'=>'', 'class'=>'pull-left errorDiv']); ?>
<?= $form->field($model, 'user_fname')->textInput(['class'=>'form-control']);?>
<?= $form->field($model, 'user_lname')->textInput(['class'=>'form-control']); ?>
<?= $form->field($model,'user_email')->textInput(['class'=>'form-control']); ?>
<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(); ?>
The scenario then check only the fields you have ruled and the submit return only the data you need
You can use the $model->isNewRecord functionality
if(!$model->isNewRecord) {
echo $form->field('Your-field')->textInput(['class' => 'form-control');
}
If I got you right you want to hide some input elements depends on your form scenario.
So, this can be easily achieved using the following code:
<?php if ($model->isUpdating()) { ?>
<?= $form->field($model, 'user_fname')->textInput(['class' => 'form-control']); ?>
<?= $form->field($model, 'user_lname')->textInput(['class' => 'form-control']); ?>
<?= $form->field($model, 'user_email')->textInput(['class' => 'form-control']); ?>
<?php } ?>
<?php if ($model->isRegistration()) { ?>
<?= $form->field($model, 'user_password_hash')->passwordInput([]); ?>
<?= $form->field($model, 'user_password_hash_repeat')->passwordInput(['class' => 'form-control']); ?>
<?php $items = ArrayHelper::map(SimAuthAssignment::find()->all(), 'item_name', 'item_name'); ?>
<?= $form->field($mode, 'item_name')->dropDownList($items, []); ?>
<?php } ?>
According to this, add the following code to the form model:
public function isUpdating() : bool {
return $this->scenario === self::SCENARIO_REGISTER;
}
public function isRegistration() : bool {
return $this->scenario === self::SCENARIO_UPDATE;
}

Yii2 Pjax on ActiveForm and GridView [ Got it Working]

I have a gridview
<?php Pjax::begin(['id' => 'members']) ?>
<?= GridView::widget([
'dataProvider' => $dataProvider,
// 'filterModel' => $searchModel,
'columns' => [
['header'=>'Remove Member',
'value'=> function($data)
{
return Html::a(Yii::t('app', ' {modelClass}', [
'modelClass' =>'',
]), ['members/stl_remove','id'=>$data->id],
['class' => 'btn btn-link fa fa-times fa-2x pop']
);
},
'format' => 'raw'
],
['class' => 'yii\grid\ActionColumn','template'=>'{update}'],
],
]); ?>
<?php Pjax::end() ?>
when i click on the Remove members link a modal popsup (delete.php)
<?php Pjax::begin(['id' => 'delete_members']) ?>
<?php $form = ActiveForm::begin(['options' => ['data-pjax' => true ]]); ?>
<div class="row">
<div class="col-md-5">
<?php echo $form->field($model, 'remarks')->dropDownList(['death' => 'Death',
'marriage' => 'Marriage', 'house_shift' => 'House Shift'],['prompt'=>'Select'])
->label("Reason For Removal"); ?>
</div>
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Remove') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
<?php yii\widgets\Pjax::end() ?>
Now these are my controller code
[code]
public function actionStl_remove($id,$ajax=0)
{
$model = $this->findModel($id);
$model_delete = new Members();
$model->scenario = "remove";
if ($model_delete->load(Yii::$app->request->post()))
{
$model->remarks = $model_delete->remarks;
$model->status = 1;
$model->save();
// $model = new Members();
// return $this->redirect(['index']);
}
else
{
return $this->renderAjax('delete', [
'model' => $model_delete,
'id' => $id,
]);
}
}
I am not able to get data loaded into gridview. I click on the link modal popsup then i submit after that i go on to the index page and the page reloads
This is how i got it working. In delete.php i made following changes.
<?php $form = ActiveForm::begin([
'options' => ['data-pjax' => true,
'id'=> 'dynamic-form111',
// 'validationUrl' => 'validation-rul'
]]); ?>
<div class="row">
<div class="col-md-5">
<?php echo $form->field($model, 'remarks')->dropDownList(['death' => 'Death',
'marriage' => 'Marriage', 'house_shift' => 'House Shift'],['prompt'=>'Select'])
->label("Reason For Removal"); ?>
</div>
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Remove') : Yii::t('app', 'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
basically i gave an id to the from dynamic-form111.
Then in index.php along with gridview in pjax i added the below code
<?php
$this->registerJs(
'jQuery(document).ready(function($){
$(document).ready(function () {
$("body").on("beforeSubmit", "form#dynamic-form111", function () {
var form = $(this);
// return false if form still have some validation errors
if (form.find(".has-error").length)
{
return false;
}
// submit form
$.ajax({
url : form.attr("action"),
type : "post",
data : form.serialize(),
success: function (response)
{
$("#ajaxModal").modal("toggle");
$.pjax.reload({container:"#countries"}); //for pjax update
},
error : function ()
{
console.log("internal server error");
}
});
return false;
});
});
});'
);
?>
which via ajax check if delete.php has been submitted successfully if yes then reloads gridview using pjax and closes modal.