diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 0a51163850..c15a1594c0 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -34,6 +34,7 @@ Yii Framework 2 Change Log - Enh #7255: Added support to allow widgets that use text input to specify input types (qiangxue) - Enh #7269: `yii\console\controllers\BaseMigrateController` now throws exception if directory specified doesn't exist and action isn't `create` (lynicidn, samdark) - Enh #7357: Refactored `yii\db\ColumnSchema` by adding `typecast()` method to decouple `phpTypecast()` from `dbTypecast()` (mcd-php, qiangxue) +- Enh #7361: The `trim` validator now works on the client side too (qiangxue) - Enh: Added support to `yii\di\Container` to instantiate and configure an object that implements `yii\base\Configurable` (qiangxue) - Chg #5690: adjusted paths in message config generated by `yii message/config` to reflect directory structure better (mikehaertl, samdark) - Chg #6661: Hyperlinks that are enclosed within an exist form will use the same form for submission if they specify both of the `href` and `data-method` attributes (qiangxue) diff --git a/framework/assets/yii.activeForm.js b/framework/assets/yii.activeForm.js index ace419f618..116d1a428e 100644 --- a/framework/assets/yii.activeForm.js +++ b/framework/assets/yii.activeForm.js @@ -291,7 +291,7 @@ $form.trigger(event, [this, msg, deferreds]); if (event.result !== false) { if (this.validate) { - this.validate(this, getValue($form, this), msg, deferreds); + this.validate(this, getValue($form, this), msg, deferreds, $form); } if (this.enableAjaxValidation) { needAjaxValidation = true; diff --git a/framework/assets/yii.validation.js b/framework/assets/yii.validation.js index 15a84e7b74..824ab134e6 100644 --- a/framework/assets/yii.validation.js +++ b/framework/assets/yii.validation.js @@ -233,6 +233,14 @@ yii.validation = (function ($) { } }, + trim: function ($form, attribute, options) { + var $input = $form.find(attribute.input); + var value = $input.val(); + if (!options.skipOnEmpty || !pub.isEmpty(value)) { + $input.val($.trim(value)); + } + }, + captcha: function (value, messages, options) { if (options.skipOnEmpty && pub.isEmpty(value)) { return; diff --git a/framework/validators/FilterValidator.php b/framework/validators/FilterValidator.php index 0b6abf69f5..d2d3cb7d73 100644 --- a/framework/validators/FilterValidator.php +++ b/framework/validators/FilterValidator.php @@ -72,4 +72,23 @@ class FilterValidator extends Validator $model->$attribute = call_user_func($this->filter, $value); } } + + /** + * @inheritdoc + */ + public function clientValidateAttribute($model, $attribute, $view) + { + if ($this->filter !== 'trim') { + return null; + } + + $options = []; + if ($this->skipOnEmpty) { + $options['skipOnEmpty'] = 1; + } + + ValidationAsset::register($view); + + return 'yii.validation.trim($form, attribute, ' . json_encode($options, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE) . ');'; + } } diff --git a/framework/widgets/ActiveField.php b/framework/widgets/ActiveField.php index 4250ddce8a..1294ffdbc3 100644 --- a/framework/widgets/ActiveField.php +++ b/framework/widgets/ActiveField.php @@ -787,7 +787,7 @@ class ActiveField extends Component } if (!empty($validators)) { - $options['validate'] = new JsExpression("function (attribute, value, messages, deferred) {" . implode('', $validators) . '}'); + $options['validate'] = new JsExpression("function (attribute, value, messages, deferred, \$form) {" . implode('', $validators) . '}'); } // only get the options that are different from the default ones (set in yii.activeForm.js)