diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 19a3da0aae..1b792305c1 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -152,6 +152,7 @@ Yii Framework 2 Change Log - Enh #4297: Added check for DOM extension to requirements (samdark) - Enh #4317: Added `absoluteAuthTimeout` to yii\web\User (ivokund, nkovacs) - Enh #4360: Added client validation support for file validator (Skysplit) +- Enh #4436: Added callback functions to AJAX-based form validation (thiagotalma) - Enh: Added support for using sub-queries when building a DB query with `IN` condition (qiangxue) - Enh: Supported adding a new response formatter without the need to reconfigure existing formatters (qiangxue) - Enh: Added `yii\web\UrlManager::addRules()` to simplify adding new URL rules (qiangxue) diff --git a/framework/assets/yii.activeForm.js b/framework/assets/yii.activeForm.js index 194fb7de1c..9f8c6159d3 100644 --- a/framework/assets/yii.activeForm.js +++ b/framework/assets/yii.activeForm.js @@ -44,6 +44,12 @@ // a callback that is called after an attribute is validated. The signature of the callback should be: // function ($form, attribute, messages) afterValidate: undefined, + // a pre-request callback function on AJAX-based validation. The signature of the callback should be: + // function ($form, jqXHR, textStatus) + ajaxBeforeSend: undefined, + // a function to be called when the request finishes on AJAX-based validation. The signature of the callback should be: + // function ($form, jqXHR, textStatus) + ajaxComplete: undefined, // the GET parameter name indicating an AJAX-based validation ajaxParam: 'ajax', // the type of data that you're expecting back from the server @@ -306,6 +312,16 @@ type: $form.prop('method'), data: $form.serialize() + extData, dataType: data.settings.ajaxDataType, + complete: function (jqXHR, textStatus) { + if (data.settings.ajaxComplete) { + data.settings.ajaxComplete($form, jqXHR, textStatus); + } + }, + beforeSend: function (jqXHR, textStatus) { + if (data.settings.ajaxBeforeSend) { + data.settings.ajaxBeforeSend($form, jqXHR, textStatus); + } + }, success: function (msgs) { if (msgs !== null && typeof msgs === 'object') { $.each(data.attributes, function () { diff --git a/framework/widgets/ActiveForm.php b/framework/widgets/ActiveForm.php index 5794d8a4f2..2821c22e18 100644 --- a/framework/widgets/ActiveForm.php +++ b/framework/widgets/ActiveForm.php @@ -151,6 +151,26 @@ class ActiveForm extends Widget * ~~~ */ public $afterValidate; + /** + * @var string|JsExpression a JS pre-request callback function on AJAX-based validation. + * The signature of the callback should be: + * + * ~~~ + * function ($form, jqXHR, textStatus) { + * } + * ~~~ + */ + public $ajaxBeforeSend; + /** + * @var string|JsExpression a JS callback to be called when the request finishes on AJAX-based validation. + * The signature of the callback should be: + * + * ~~~ + * function ($form, jqXHR, textStatus) { + * } + * ~~~ + */ + public $ajaxComplete; /** * @var array the client validation options for individual attributes. Each element of the array * represents the validation options for a particular attribute. @@ -208,7 +228,7 @@ class ActiveForm extends Widget if ($this->validationUrl !== null) { $options['validationUrl'] = Url::to($this->validationUrl); } - foreach (['beforeSubmit', 'beforeValidate', 'afterValidate'] as $name) { + foreach (['beforeSubmit', 'beforeValidate', 'afterValidate', 'ajaxBeforeSend', 'ajaxComplete'] as $name) { if (($value = $this->$name) !== null) { $options[$name] = $value instanceof JsExpression ? $value : new JsExpression($value); }