samdark / yii2-cookbook

Yii 2.0 Community Cookbook
1.45k stars 296 forks source link

Suggestion: determine whether validation was successful in js activeform "afterValidate" event #167

Open vercotux opened 7 years ago

vercotux commented 7 years ago

Seems like a very trivial, common requirement, but there doesn't seem to be any simple way to know whether validation was successful inside the afterValidate client event. How do we do it?

This would fit perfectly into the Forms activeform js chapter.

samdark commented 7 years ago

Can't you check length of errorAttributes?

function (event, messages, errorAttributes) {
    if (errorAttributes.length) {
        // not valid
    } else {
       // valid
    }
}
vercotux commented 7 years ago

That was what I initially tried, but it does not work, because errorAttributes does not contain all validation errors, so you will get false positives. It only contains validation errors of fields rendered by ActiveForm! Meaning if you used something like

<?= Html::activeHiddenInput($model, 'test'); ?>

then test would not be part of errorAttributes even when it has validation errors!

Now, this would all sort of make sense, if we were dealing purely with client-side validation. After all, client-side does not know if there are any validation errors on the server-side... until you introduce AJAX validation! :)

With AJAX validation, we do know if there were server-side validation errors, so we should be able to know if validation was successful in the afterValidate event. But how? We cannot rely on errorAttributes because it does not contain server-side validation errors even when using AJAX validation. Maybe this is a bug?

samdark commented 7 years ago

According to code it should be available in AJAX validation as well. Please create a ticket in the main Yii 2.0 repo with a clear way to reproduce the issue. Thanks.

vercotux commented 7 years ago

Alright. In the meantime I have found a working solution. Turns out that messages inside afterValidate will always contain error messages (including those coming from AJAX validation!), no matter how we rendered our ActiveForm. We can use this function to reliably determine whether validation was successful:

function isValid(messages) {
    for (var i in messages) {
        if (messages[i].length>0) {
            return false;
        }
    }
    return true;
}

Usage example:

function (event, messages, errorAttributes) {
    if (isValid(messages)) {
        // valid
    } else {
       // not valid
    }
}
samdark commented 7 years ago

Great. Would you like to make a pull request adding it to recipe?