Yii2: afterValidate event behaviour changed

Created on 31 Jul 2019  路  10Comments  路  Source: yiisoft/yii2

afterValidate is now always called after validation is done.
This used to be only when the form was submited which breaks our code (and possibly others as well).

Additional info

it happens on 2.0.23
it does not happen on 2.0.19

I think the problem is with this commit introduced in 2.0.21

You can see that the if (submitting) statement is moved under the form trigger.

JS to be verified bug

Most helpful comment

@samdark should I add a new event that can trigger when the form validates regardless if it is submitted, and revert afterValidate to its original behavior?

All 10 comments

@czzplnm do you have some time to look into it?

@czzplnm do you have some time to look into it?

Yeah, I'll take a look.

You can see that the if (submitting) statement is moved under the form trigger.

@thomaswelter

The purpose of my change was to allow 'afterValidate' to trigger when the form was not submitting.

Our use case was a submit button would be 'disabled' until afterValidate notified us that everything was valid, then we would allow the user to submit the form. Before afterValidate only triggers when the form is submitting.

I can't find anything that would cause this in the code, but I will test it myself, but can you clarify your use case please.

If I understand it properly: Your activeForm has ajax validation, and you are doing validateOnChange, or you are detecting the change yourself and invoking validateAttribute on the element manually?

The way we currently use afterValidate is to show an alert to the user to show that some fields need attention. This is also shown under the input itself but that input might be on another page.

I could use BeforeSubmit but the problem is that it only fires if there were no validation errors.

I'l admit that the way you want to use afterValidate makes more sense. This is however a breaking change. I can see the use case as i had the same problem before. I suggest we create a new event that triggers after all validations are checked (after all afterValidateAttribute events) regardless of a form being submitted. It could be named attributesValidated for example.

Note: Now that i looked into the code the way i stated the problem was wrong, i will update that.

Also ran into a problem due to this change. I have a form with ajax validation and the behavior I needed before was during validation before submitting the form. Now the event is triggered even with ajax validation. When you change field on the form and send AJAX validation request to server (on validation URL), an event "afterValidate" now is triggered (before event triggered only after Submit form). I'm not sure which behavior is correct, but I had to insert check on submit in JS.

$('form#{$model->formName()}').on('afterValidate', function(event,messages)
{
    if($(this).data('yiiActiveForm').submitting === false){
         return;   
       //This change is necessary so that the window with errors appears only when you click Submit and not after losing the focus of any field.
    }
    if(messages && typeof(messages) == "object"){
        var out = '';
        for (var i in messages) {
            if(messages[i] != ''){
                out += '<li>'+messages[i]+'</li>';
            }
        }
        if(out.length > 0){
                out = "<ul><h3 class=\'text-danger\'>"+out+'</h3></ul>';
                bootbox.dialog({message: out,onEscape: true,backdrop: true})
        }
    }
});

@samdark
What do you think?

Options are:

  1. Revert behavior to pre 2.0.21
  2. Adjust it to satisfy both use cases
  3. Keep it as it is. Then we need to describe how to get old behavior in UPGRADE.md

As I understand, variant 2 is not possible because new behavior directly contradicts old one.

@samdark should I add a new event that can trigger when the form validates regardless if it is submitted, and revert afterValidate to its original behavior?

Yes. I think that is a must if we want to keep current behavior.

This update broke our logic a bit too. So, yes, another vote to revert afterValidate behavior.

A simplified case:
Field 1 with ajax validation.
Field 2 with simple required validation.
We want to draw users attention to fields with errors on the form after the form has been submitted (validated completely).

User enters valid data into Field 1, ajax validation triggered, it returns an error for Field 2 because it is empty, although this error is not shown on the form.
afterValidate is now triggered, and it tells us about error of Field 2, so we show user a message "Please check errors above for Field2", however there are no errors shown on the form :)

Was this page helpful?
0 / 5 - 0 ratings