问题
I want to make custom validation function like built-in validation required
. I have example code here:
Model:
use yii\base\Model;
class TestForm extends Model
{
public $age;
public function rules(){
return [
['age', 'my_validation']
];
}
public function my_validation(){
//some code here
}
}
View:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
$this->title = 'test';
?>
<div style="margin-top: 30px;">
<?php $form = ActiveForm::begin(); ?>
<?= $form->field($model, 'age')->label("age") ?>
<div class="form-group">
<?= Html::submitButton('submit', ['class' => 'btn btn-primary']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
Controller:
use app\models\form\TestForm;
use yii\web\Controller;
class TestController extends Controller
{
public function actionIndex(){
$model = new TestForm();
if($model->load(\Yii::$app->request->post())){
return $this->render('test', array(
'model'=>$model,
'message'=>'success'
));
}
return $this->render('test', array('model'=>$model));
}
}
in this example I have a field for age and this my_validation
function should check if age is over 18 before submit and throw error if age is under 18. This validation should be processed by ajax like it is in case of required
rule if you try to submit empty field.
回答1:
Although you can use Conditional Validators when
and whenClient
too in your scenario but I would recommend using a more sophisticated way which is to define a custom validator because according to the docs
To create a validator that supports client-side validation, you should implement the
yii\validators\Validator::clientValidateAttribute()
method which returns a piece of JavaScript code that performs the validation on the client-side. Within the JavaScript code, you may use the following predefined variables:
attribute:
the name of the attribute being validated.
value:
the value being validated.
messages:
an array used to hold the validation error messages for the attribute.
deferred:
an array which deferred objects can be pushed into (explained in the next subsection).
So what you need to do is create a validator and add it to your rules against the field you want.
You need to be careful copying the following code IF you haven't provided the actual model name and update the field names accordingly.
1) First thing to do is to update the ActiveForm
widget to the following
$form = ActiveForm::begin([
'id' => 'my-form',
'enableClientValidation' => true,
'validateOnSubmit' => true,
]);
2) Change your model rules()
function to the following
public function rules()
{
return [
[['age'], 'required'],
[['age'], \app\components\AgeValidator::className(), 'skipOnEmpty' => false, 'skipOnError' => false],
];
}
3) Remove the custom validation function my_validation()
from your model i hope you are checking the age limit in it to be 18+
we will move that logic into the validator.
Now create a file AgeValidator.php
inside components
directory, if you are using the basic-app
add the folder components
inside the root directory of the project if it does not exist create a new one, and copy the following code inside.
BUT
I have assumed the name of the Model that is provided by you above so if it not the actual name you have to update the field name inside the javascript
statements within clientValidateAttribute
function you see below in the validator because the id
attribute of the fields in ActiveForm
is generated in a format like #modelname-fieldname
(all small case) so according to above given model, it will be #testform-age
do update it accordingly otherwise the validation wont work. And do update the namespace in the validator below and in the model rules()
if you plan to save it somewhere else.
<?php
namespace app\components;
use yii\validators\Validator;
class AgeValidator extends Validator
{
public function init()
{
parent::init();
$this->message = 'You need to be above the required age 18+';
}
public function validateAttribute($model, $attribute)
{
if ($model->$attribute < 18) {
$model->addError($attribute, $this->message);
}
}
public function clientValidateAttribute($model, $attribute, $view)
{
$message = json_encode($this->message, JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE);
return <<<JS
if (parseInt($("#testform-age").val())<18) {
messages.push($message);
}
JS;
}
}
来源:https://stackoverflow.com/questions/48628100/using-custom-validators-with-activeform-in-yii2