To do it the way you want it to work you need to submit the form via AJAX and it is required to attach a handler on afterValidate event. The handler will replace default form submission and is responsible for sending data to the server and displaying error messages if server validation fails. Displaying validation messages requires support on the controller side.
You can update the form name/id respectively in the script. and add the alerts in the error and incorrect server response. your form will be automatically saved via ajax call without reloading you can reset the form inside the success part.
Attach a handler to form:
$this->registerJs('$(\'#my-form\').on(\'afterValidate\', function () {
var $yiiform = $(this);
$.ajax({
type: $yiiform.attr(\'method\'),
url: $yiiform.attr(\'action\'),
data: $yiiform.serializeArray(),
}
)
.done(function(data) {
if(data.success) {
$yiiform.submit();
// data is saved
} else if (data.validation) {
// server validation failed
$yiiform.yiiActiveForm(\'updateMessages\', data.validation, true); // renders validation messages at appropriate places
console.log("error on form"+data.validation);
} else {
console.log("incorrect server response");
// incorrect server response
}
})
.fail(function () {
console.log("request failed");
// request failed
})
return false; // prevent default form submission
})');
Just make sure you have your action coded like below
Controller action:
public function actionUpdate($id)
{
if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
//call model validate to trigger validation messages
$model->validate();
$result = [];
// The code below comes from ActiveForm::validate(). We do not need to validate the model
// again, as it was already validated by save(). Just collect the messages.
foreach ($model->getErrors() as $attribute => $errors) {
$result[\yii\helpers\Html::getInputId($model, $attribute)] = $errors;
}
if (!empty($result)) {
return $this->asJson(['validation' => $result]);
}
return $this->asJson(['success' => true]);
} elseif ($model->load(Yii::$app->request->post()) && $model->save()) {
Yii::$app->session->setFlash('success', 'Form saved successfully');
return $this->redirect('index');
}
return $this->render('form', ['model' => $model]);
}
And most important just initialize your form with the option enableClientValidation as true like below.
$form = ActiveForm::begin([
'id' => 'login-form',
'enableClientValidation' => true,
]);
2.0.13.1. I have tried this on a login form. When I enter an email address and press the tab key, I can see in the console it has performed an AJAX call.2.0.14.1withcomposer updateand then confirm2.0.14.1and same thing happens. Yes, I can see the request inside the network tab. To be honest I think this is by design, because there is no way to specify whethervalidateOnChangeandvalidateOnBlurwill apply to ajax or client validation - it applies to both by default.