Multi-field validation

I need to do a multi-field validation - something that is explained very well in so many blogs and cookooks, but I am not able to get it to work!

Here is the code:

[['orgname', 'firstname', 'lastname'], 'required', 'when' => function($model) {
    return false ;
    //return true;
    //return (empty($model->firstname) && empty($model->lastname)) ;
}],

I have tried return true/false/etc. No matter what the return is, the orgname is always required! And it seems to be doing a Javascript validation that I don’t really care for. Server validation is fine.

I then tried this:

[['orgname'], 'required1'],

public function required1($attribute, $params){
    $this->addError($attribute,'Custom Validation Error');
}

Here, even when I am forcing an error, no error shows up and the validation proceeds as if there is no error.

All I need is for the user to enter either first/last name OR orgname. Don’t want all 3 blank.

You will need to implement the client version or disable client validation

Thank you @evstevemd Can you tell me how I may disable client validation for just that field? Or if that is not possible, how to I enable it? I tried a few online examples of playing around with javascript to enable client validation but was unsuccessful. I may have to to start reading javascript eventually as I hit that limitation often!

Javascript explains the 1st option. Still not sure why the 2nd option of writing custom function does not work.

Hello snathan,

As per the Yii2 guide for conditional validation:

I think what you need to do is target each validation rule individually rather than trying to do them as a collective set. So in discussion terms (non code) the theory would be… check this current field and if this field and any of the other two associated fields are blank then you are required - else you can be blank.

You apply that rule to each of the fields so they all have the same set of rules as each other, if any of them break the rules then the form cannot be submitted - or if any one of them (or all of them) has a value then it’s ok for the form to be submitted.

In terms of the javascript client side validation I included that also for you, but you need to replace this part “multivalidationform” with the actual name of the form you created. This references the exact field id name of the form - it’s inside each of the three rules in the code below, so basically you need to replace it 3 x times.

Here is the code I wrote as an example for you:

/**
     * @return array the validation rules.
     */
    public function rules()
    {
        return [
            ['first_name', 'required', 'when' => function ($model) {
                return (empty($model->first_name) && empty($model->last_name) && empty($model->orgname));
            }, 'whenClient' => "function (attribute, value) {
                return ($('#multivalidationform-first_name').val() == '' && $('#multivalidationform-last_name').val() == '' && $('#multivalidationform-orgname').val() == '');
            }"],
            ['last_name', 'required', 'when' => function ($model) {
                return (empty($model->first_name) && empty($model->last_name) && empty($model->orgname));
            }, 'whenClient' => "function (attribute, value) {
                return ($('#multivalidationform-first_name').val() == '' && $('#multivalidationform-last_name').val() == '' && $('#multivalidationform-orgname').val() == '');
            }"],
            ['orgname', 'required', 'when' => function ($model) {
                return (empty($model->first_name) && empty($model->last_name) && empty($model->orgname));
            }, 'whenClient' => "function (attribute, value) {
                return ($('#multivalidationform-first_name').val() == '' && $('#multivalidationform-last_name').val() == '' && $('#multivalidationform-orgname').val() == '');
            }"]
        ];
    }

I hope it works for you.

Edit: The name of your form is in your view file like so (without the hyphens):

<?php $form = ActiveForm::begin(['id' => 'multi-validation-form']); ?>

I called mine “multi-validation-form”, use your code inspector to see the name of the input id for each one.

2 Likes

It worked! Thank you @replicant_k for not only just providing the answer but writing the code for me. Very much appreciated.

Nice one snathan - glad you got it working! You’re welcome.

For completeness sake, here is how you disable field from validation. See ActiveField docs for more details

 <?= $form->field($client, 'field_name')
    ->textInput(['enableClientValidation' => false])  ?>

Thank you @evstevemd. Good to know indeed.

1 Like