I have a form with two fields "a" and "b" when in action update if the "b" field changes the "beforeSubmit" event a Modal Bootstrap alert is sent to the user without any button OK
or CANCEL
, only information during 5 seconds, after this time automatically save if the the "b" field were actually changed, if not change save whitout alert modal windows.
How do I send this condition from the controller to view where I have the javascript? maybe with ajax? but how?
Controller.php
public function actionUpdate()
{
$model = new Faqs();
if ($model->load(Yii::$app->request->post()) && $model->save()) {
if ($model->oldAttributes["b"] != $model->b){
sleep(5);
}
return $this->redirect(['view', 'id' => $model->id]);
} else {
return $this->render('update', [
'model' => $model,
]);
}
}
_form.php
$('#form').on('beforeSubmit', function(e) {
if(old_B_attribute != current_B_attribute){ //example
$('#modal').modal('show');
}
});
You want to prompt the user if the attribute values were actually changed before submitting the form.
How I would go for this
actionAttributeDirty()
which would validate if the selected attribute was actually changed.Html::button()
rather than a Html::submitButton()
for the form.id
in the form.click
event to the button which will send an ajax call to actionAttributeDirty()
with the id
of the current record.setTimeout
with $.yiiActiveForm('submitForm')
to trigger the form submission after 5 seconds.So in the similar order given above,
actionAttributeDirty
public function actionAttributeDirty()
{
Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
$id = Yii::$app->request->post('id');
$model = Faqs::findOne($id);
$response = ['changed' => false];
$isValidRequest = Yii::$app->request->isAjax && Yii::$app->request->isPost;
if ($isValidRequest && $model->load(Yii::$app->request->post())) {
//get the name of the fields from the dirty attributes
$changedAttributes = array_keys($model->getDirtyAttributes());
//if the attribute name exists in the dirty attributes
if (!empty($changedAttributes) && in_array("b", $changedAttributes)) {
$response['changed'] = true;
}
}
return $response;
}
Your form should have the following buttons along with other fields,
$form = \yii\widgets\ActiveForm::begin(['id' => 'form']);
echo \yii\helpers\Html::hiddenInput('id', $model->id);
echo \yii\helper\Html::button('save', ['id' => 'save-now']);
\yii\widgets\ActiveForm::end();
click
Event for the Button
Add the following on the top of your view where you have the form.
Note: change the url
of the ajax call '/site/attribute-dirty'
accordingly where you copy the actionAttributeDirty()
i assume you copy it inside the site controller.
$js = <<< JS
$('#save-now').on('click', function(e) {
e.preventDefault();
let form = $("#form");
$.ajax({
url:'/site/attribute-dirty',
method:'post',
data:form.serialize(),
}).done(function(response){
if(response.changed){
$('#modal').modal('show');
setTimeout(function(){form.yiiActiveForm('submitForm');}
, 5000);
}else{
form.yiiActiveForm('submitForm');
}
}).fail(function(response){
console.log(response.responseText);
});
});
JS;
$this->registerJs($js, \yii\web\View::POS_READY);
EDIT
Pressing Enter button will not submit the form anyhow as there is no submit button, If you want Enter button to submit the form you should add the following along with the script too on the top of the view which will trigger the click
event of the save-now
button whenever the Enter button is pressed within any input.
$("#form").on('keypress','input',function(e){
e.preventDefault();
if(e.keyCode===13){
$("#save-now").trigger('click');
}
});