diff --git a/framework/assets/yii.activeForm.js b/framework/assets/yii.activeForm.js index 901deac..5569447 100644 --- a/framework/assets/yii.activeForm.js +++ b/framework/assets/yii.activeForm.js @@ -23,6 +23,8 @@ }; var defaults = { + // the jQuery selector for the error summary + errorSummary: undefined, // whether to enable client-side (JavaScript) validation enableClientValidation: true, // whether to enable AJAX-based validation @@ -381,7 +383,7 @@ var updateSummary = function ($form, messages) { var data = $form.data('yiiActiveForm'), - $summary = $form.find(data.settings.summary), + $summary = $form.find(data.settings.errorSummary), content = ''; if ($summary.length && messages) { diff --git a/framework/validators/Validator.php b/framework/validators/Validator.php index 2460081..677191b 100644 --- a/framework/validators/Validator.php +++ b/framework/validators/Validator.php @@ -101,6 +101,13 @@ abstract class Validator extends Component * is null or an empty string. */ public $skipOnEmpty = true; + /** + * @var boolean whether to enable client-side validation for this validator. + * The actual client-side validation is done via the JavaScript code returned + * by [[clientValidateAttribute()]]. If that method returns null, even if this property + * is true, no client-side validation will be done by this validator. + */ + public $enableClientValidation = true; /** * Validates a single attribute. diff --git a/framework/widgets/ActiveField.php b/framework/widgets/ActiveField.php index 90c6db4..060fe7e 100644 --- a/framework/widgets/ActiveField.php +++ b/framework/widgets/ActiveField.php @@ -57,7 +57,67 @@ class ActiveField extends Component * without the `$options` parameter. */ public $labelOptions = array('class' => 'control-label'); - + /** + * @var boolean whether to enable client-side data validation. + * If not set, it will take the value of [[ActiveForm::enableClientValidation]]. + */ + public $enableClientValidation; + /** + * @var boolean whether to enable AJAX-based data validation. + * If not set, it will take the value of [[ActiveForm::enableAjaxValidation]]. + */ + public $enableAjaxValidation; + /** + * @var boolean whether to perform validation when the input field loses focus and its value is found changed. + * If not set, it will take the value of [[ActiveForm::validateOnChange]]. + */ + public $validateOnChange; + /** + * @var boolean whether to perform validation while the user is typing in the input field. + * If not set, it will take the value of [[ActiveForm::validateOnType]]. + * @see validationDelay + */ + public $validateOnType; + /** + * @var integer number of milliseconds that the validation should be delayed when a user is typing in an input field. + * This property is used only when [[validateOnType]] is true. + * If not set, it will take the value of [[ActiveForm::validationDelay]]. + */ + public $validationDelay; + /** + * @var JsExpression|string a [[JsExpression]] object or a JavaScript expression string representing + * the callback that will be invoked BEFORE validating the attribute associated with this field on the client side. + * + * This callback is called after [[ActiveForm::beforeValidateAttribute]]. + * + * The signature of the callback should be like the following: + * + * ~~~ + * ~~~ + */ + public $beforeValidate; + /** + * @var JsExpression|string a [[JsExpression]] object or a JavaScript expression string representing + * the callback that will be invoked AFTER validating the attribute associated with this field on the client side. + * + * This callback is called before [[ActiveForm::afterValidateAttribute]]. + * + * The signature of the callback should be like the following: + * + * ~~~ + * ~~~ + */ + public $afterValidate; + /** + * @var array the jQuery selectors for selecting the container, input and error tags. + * The array keys should be "container", "input", and/or "error", and the array values + * are the corresponding selectors. For example, `array('input' => '#my-input')`. + * + * The selectors are used under the context of the form. + * + * You normally do not need to set this property as the default selectors should work well for most cases. + */ + public $selectors; public function begin() { diff --git a/framework/widgets/ActiveForm.php b/framework/widgets/ActiveForm.php index bc55e82..aefa9e9 100644 --- a/framework/widgets/ActiveForm.php +++ b/framework/widgets/ActiveForm.php @@ -12,6 +12,7 @@ use yii\base\Widget; use yii\base\Model; use yii\helpers\Html; use yii\helpers\Json; +use yii\helpers\JsExpression; /** * ActiveForm ... @@ -37,25 +38,16 @@ class ActiveForm extends Widget */ public $options = array(); /** - * @var string the default CSS class for the error summary container. - * @see errorSummary() - */ - public $errorSummaryCssClass = 'yii-error-summary'; - /** * @var array the default configuration used by [[field()]] when creating a new field object. */ public $fieldConfig = array( 'class' => 'yii\widgets\ActiveField', ); - /** - * @var boolean whether to enable client-side data validation. - * Client-side validation will be performed by validators that support it - * (see [[\yii\validators\Validator::enableClientValidation]] and [[\yii\validators\Validator::clientValidateAttribute()]]). + * @var string the default CSS class for the error summary container. + * @see errorSummary() */ - public $enableClientValidation = true; - public $enableAjaxValidation = false; - + public $errorSummaryCssClass = 'yii-error-summary'; /** * @var string the CSS class that is added to a field container when the associated attribute is required. */ @@ -72,12 +64,92 @@ class ActiveForm extends Widget * @var string the CSS class that is added to a field container when the associated attribute is being validated. */ public $validatingCssClass = 'validating'; - + /** + * @var boolean whether to enable client-side data validation. + * If [[ActiveField::enableClientValidation]] is set, its value will take precedence for that input field. + */ + public $enableClientValidation = true; + /** + * @var boolean whether to enable AJAX-based data validation. + * If [[ActiveField::enableAjaxValidation]] is set, its value will take precedence for that input field. + */ + public $enableAjaxValidation = false; + /** + * @var array|string the URL for performing AJAX-based validation. This property will be processed by + * [[Html::url()]]. Please refer to [[Html::url()]] for more details on how to configure this property. + * If this property is not set, it will take the value of the form's action attribute. + */ public $validationUrl; - public $validationDelay; - public $validateOnChange; - public $validateOnType; - + /** + * @var boolean whether to perform validation when the form is submitted. + */ + public $validateOnSubmit = true; + /** + * @var boolean whether to perform validation when an input field loses focus and its value is found changed. + * If [[ActiveField::validateOnChange]] is set, its value will take precedence for that input field. + */ + public $validateOnChange = false; + /** + * @var boolean whether to perform validation while the user is typing in an input field. + * If [[ActiveField::validateOnType]] is set, its value will take precedence for that input field. + * @see validationDelay + */ + public $validateOnType = false; + /** + * @var integer number of milliseconds that the validation should be delayed when a user is typing in an input field. + * This property is used only when [[validateOnType]] is true. + * If [[ActiveField::validationDelay]] is set, its value will take precedence for that input field. + */ + public $validationDelay = 200; + /** + * @var JsExpression|string a [[JsExpression]] object or a JavaScript expression string representing + * the callback that will be invoked BEFORE validating EACH attribute on the client side. + * The signature of the callback should be like the following: + * + * ~~~ + * ~~~ + */ + public $beforeValidateAttribute; + /** + * @var JsExpression|string a [[JsExpression]] object or a JavaScript expression string representing + * the callback that will be invoked AFTER validating EACH attribute on the client side. + * The signature of the callback should be like the following: + * + * ~~~ + * ~~~ + */ + public $afterValidateAttribute; + /** + * @var JsExpression|string a [[JsExpression]] object or a JavaScript expression string representing + * the callback that will be invoked BEFORE validating ALL attributes on the client side when the validation + * is triggered by form submission (that is, [[validateOnSubmit]] is set true). + * + * This callback is called before [[beforeValidateAttribute]]. + * + * The signature of the callback should be like the following: + * + * ~~~ + * ~~~ + */ + public $beforeValidate; + /** + * @var JsExpression|string a [[JsExpression]] object or a JavaScript expression string representing + * the callback that will be invoked AFTER validating ALL attributes on the client side when the validation + * is triggered by form submission (that is, [[validateOnSubmit]] is set true). + * + * This callback is called after [[afterValidateAttribute]]. + * + * The signature of the callback should be like the following: + * + * ~~~ + * ~~~ + */ + public $afterValidate; + /** + * @var array list of attributes that need to be validated on the client side. Each element of the array + * represents the validation options for a particular attribute. + * @internal + */ public $attributes = array(); /** @@ -98,7 +170,18 @@ class ActiveForm extends Widget */ public function run() { - $id = $this->options['id']; + if ($this->attributes !== array()) { + $id = $this->options['id']; + $options = Json::encode($this->getClientOptions()); + $attributes = Json::encode($this->attributes); + $this->view->registerAssetBundle('yii/form'); + $this->view->registerJs("jQuery('#$id').yiiActiveForm($attributes, $options);"); + } + echo Html::endForm(); + } + + protected function getClientOptions() + { $options = array( 'enableClientValidation' => $this->enableClientValidation, 'enableAjaxValidation' => $this->enableAjaxValidation, @@ -106,11 +189,6 @@ class ActiveForm extends Widget 'successCssClass' => $this->successCssClass, 'validatingCssClass' => $this->validatingCssClass, ); - $options = Json::encode($options); - $attributes = Json::encode($this->attributes); - $this->view->registerAssetBundle('yii/form'); - $this->view->registerJs("jQuery('#$id').yiiActiveForm($attributes, $options);"); - echo Html::endForm(); } /**