diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 2efcab83c7..676de934ce 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -168,6 +168,7 @@ Yii Framework 2 Change Log - Enh #4436: Added callback functions to AJAX-based form validation (thiagotalma) - Enh #4485: Added support for deferred validation in `ActiveForm` (Alex-Code) - Enh #4520: Added sasl support to `yii\caching\MemCache` (xjflyttp) +- Enh #4559: Added `beforeValidateAll` and `afterValidateAll` callbacks to `ActiveForm` (Alex-Code) - Enh #4566: Added client validation support for image validator (Skysplit, qiangxue) - Enh #4581: Added ability to disable url encoding in `UrlRule` (tadaszelvys) - Enh: Added support for using sub-queries when building a DB query with `IN` condition (qiangxue) diff --git a/framework/assets/yii.activeForm.js b/framework/assets/yii.activeForm.js index bab3fb5936..5f2a3e2220 100644 --- a/framework/assets/yii.activeForm.js +++ b/framework/assets/yii.activeForm.js @@ -41,9 +41,15 @@ // a callback that is called before validating each attribute. The signature of the callback should be: // function ($form, attribute, messages) { ...return false to cancel the validation...} beforeValidate: undefined, + // a callback that is called before validation starts (This callback is only called when the form is submitted). This signature of the callback should be: + // function($form, data) { ...return false to cancel the validation...} + beforeValidateAll: undefined, // a callback that is called after an attribute is validated. The signature of the callback should be: // function ($form, attribute, messages) afterValidate: undefined, + // a callback that is called after all validation has run (This callback is only called when the form is submitted). The signature of the callback should be: + // function ($form, data, messages) + afterValidateAll: undefined, // a pre-request callback function on AJAX-based validation. The signature of the callback should be: // function ($form, jqXHR, textStatus) ajaxBeforeSend: undefined, @@ -152,6 +158,11 @@ clearTimeout(data.settings.timer); } data.submitting = true; + + if (data.settings.beforeValidateAll && !data.settings.beforeValidateAll($form, data)) { + data.submitting = false; + return false; + } validate($form, function (messages) { var errors = []; $.each(data.attributes, function () { @@ -159,6 +170,11 @@ errors.push(this.input); } }); + + if (data.settings.afterValidateAll) { + data.settings.afterValidateAll($form, data, messages); + } + updateSummary($form, messages); if (errors.length) { var top = $form.find(errors.join(',')).first().offset().top; diff --git a/framework/widgets/ActiveForm.php b/framework/widgets/ActiveForm.php index 320d553e9d..7484630c68 100644 --- a/framework/widgets/ActiveForm.php +++ b/framework/widgets/ActiveForm.php @@ -141,6 +141,17 @@ class ActiveForm extends Widget * ~~~ */ public $beforeValidate; + /** + * @var string|JsExpression a JS callback that is called before any validation has run (Only called when the form is submitted). + * The signature of the callback should be: + * + * ~~~ + * function ($form, data) { + * ...return false to cancel the validation... + * } + * ~~~ + */ + public $beforeValidateAll; /** * @var string|JsExpression a JS callback that is called after validating an attribute. * The signature of the callback should be: @@ -151,6 +162,16 @@ class ActiveForm extends Widget * ~~~ */ public $afterValidate; + /** + * @var string|JsExpression a JS callback that is called after all validation has run (Only called when the form is submitted). + * The signature of the callback should be: + * + * ~~~ + * function ($form, data, messages) { + * } + * ~~~ + */ + public $afterValidateAll; /** * @var string|JsExpression a JS pre-request callback function on AJAX-based validation. * The signature of the callback should be: @@ -229,7 +250,7 @@ class ActiveForm extends Widget if ($this->validationUrl !== null) { $options['validationUrl'] = Url::to($this->validationUrl); } - foreach (['beforeSubmit', 'beforeValidate', 'afterValidate', 'ajaxBeforeSend', 'ajaxComplete'] as $name) { + foreach (['beforeSubmit', 'beforeValidate', 'beforeValidateAll', 'afterValidate', 'afterValidateAll', 'ajaxBeforeSend', 'ajaxComplete'] as $name) { if (($value = $this->$name) !== null) { $options[$name] = $value instanceof JsExpression ? $value : new JsExpression($value); }