Own validation rules for a model

On https://www.yiiframework.com/wiki/168/create-your-own-validation-rule if found informations to add own validation rules for a model.

But my problem is, that i want to save targets for a customer in a target database table. In these table i saved the target name and the customer id. Now i want check with a validation rule, if the target name for these customer is exists. Then i want show a error in the form.

The unique rule is not enough for me because I have to pass the customer id to the rule. Is this possible with yii2?

Ok. I solved the problem with my own rule.

Here is an excerpt of the code:

In Model

    public function rules()
    {
        return [
            [['target_name'], 'checkAddTarget'],
        ];
    }

    public function checkAddTarget($attribute, $params) {
        if(self::find()->where(['target_name' => $this->$attribute, 'k_id'=>$this->k_id])->one()==true){
            $this->addError($attribute, 'Targetname für '.$this->k_id.' bereits vorhanden');
            return false;
        }
    }

If I validate the model in Controller, the rule is executed and a corresponding error message is generated, which I can read out with $model->errors.

But during form entry, this rule is not checked. It is only checked whether the field has an input or not. The rule is only used when saving with $model->save() in the controller.

Can someone give me a tip on this?

2 Likes

Perhaps ajaxValidation
https://www.yiiframework.com/doc/guide/2.0/en/input-validation#ajax-validation

1 Like

Thanks Tommy, but i have check this and this also dosn’t work.

In the same formular i used a field for the ip-range. And i used a yii-rule for check the ip-range. This rule will be checked by the formular. But the own rule dosn’t.

If your validator works as expected in the server side, then you should be able to use it in ajaxValidation. Double check the source code in the _form.php. Does it enable the ajax validation for the ‘target_name’ field?

There are 2 kinds of validators: one that supports clientValidation and the other that doesn’t.

  • require, in, compare, string, number, … supports clientValidation
  • exist, unique, … doesn’t

When you write your own validator, you may want it to support clientValidation. You can do so if you can implement clientValidateAttribute() that delivers a javascript to validate the input value in the client side.

But when you have to access db in order to do validation, probably you can not implement client side validation. In that case, the only solution might be using ajaxValidation as @tri suggested.

Guide > Getting Data from User > Client-side Validation

1 Like

Now i used ajax validation in a normal view site. All works fine.

But when i load the form with an ajax function, the ajax validation dosn’t work.

Here is my code:

The function who load the form:

    public function actionAjax_userdataedit($show)
    {

        // if this is a ajax request 
        if (Yii::$app->request->getIsAjax()) {
            
            $model = User::findOne(['id' => Yii::$app->user->identity->id]);

            // render the form to add a new Target
            $content=$this->renderPartial('ajax_userdataedit', [
                'show' => $show,
                'UserData' => User::loadUserDataArray(),
                'model' => $model,
            ]);

            // change the response format to JSON for the ajax function
            Yii::$app->response->format = \yii\web\Response::FORMAT_JSON;
            $data['content']=$content;

            return $data;

        } else {

             // show error page
             return $this->render('error');

        }
    }

Here the code from the formular:

    $form = ActiveForm::begin(['action' =>['useraccount'], 
                               'enableAjaxValidation' => true, 
                               'validationUrl' => ['/dashboard/ajaxvalidation'],
                               'enableClientValidation'=>false, 
                               'options'=>['class'=>'formular']]);

In the Dashboard Controller i have the function actionAjaxvailidation they looks like:

    public function actionAjaxvalidation() {
        $model = User::findOne(['id' => Yii::$app->user->identity->id]);
        if (Yii::$app->request->isAjax && $model->load(Yii::$app->request->post())) {
            Yii::$app->response->format = Response::FORMAT_JSON;
            return ActiveForm::validate($model);
        }
    }

I don’t no where the problem is.

This is an expected result when a form is rendered using renderPartial() through ajax response. The javascript for the ajax validation won’t be registered.

Try renderAjax() instead of renderPartial().

Guide > Views > Rendering in Controllers

1 Like

I’ve changed in renderAjax but it dosn’t work. No reaction.

Must i register the javascript for the ajax validation after i load the form?

Try change the response format to Response::FORMAT_HTML

then i became the error

Exception 'yii\base\InvalidArgumentException' with message 'Response content must not be an array.'

I give the content back to the ajax function which call the view. here is the code:

    $.ajax({
        url: 'ajax_userdataedit?show='+show, 
        dataType: 'JSON',  
        data: "show="+show, //$(this).serialize(),                      
        type: 'post',                        
        beforeSend: function() {
        },
        success: function(response){                      
            $('#userdata').html(response['content']);

Now i have change the ajax function to

    $.ajax({
        url: 'ajax_userdataedit?show='+show, 
        dataType: 'HTML',  
        data: "show="+show, //$(this).serialize(),                      
        type: 'post',                        
        beforeSend: function() {
        },
        success: function(response){           
            $('#userdata').html(response);

The form is loading but the ajax validation dosn’t work again.

Now i give the form an id and it works. that’s weird

1 Like

Weird, but must have some reason. I don’t know.

This might have been unneccessary change. Probably you could use `Rresponse::FORMAT_JSON’, too.