Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Forced validation in yiiActiveForm do not trigger afterValidate event #14186

Closed
lenyy opened this issue May 22, 2017 · 8 comments
Closed

Forced validation in yiiActiveForm do not trigger afterValidate event #14186

lenyy opened this issue May 22, 2017 · 8 comments
Assignees
Labels
JS JavaScript related type:bug Bug
Milestone

Comments

@lenyy
Copy link

lenyy commented May 22, 2017

Hi there, so for me YiiActiveForm is not performing validation on field when is set manually so i need your help to check if its my problem or Yii.
From the Yii cookbook if we want to perform validation on form we just need to call

$('#contact-form').yiiActiveForm('validate', true);

we assume that it should validate the whole form and send the event afterValidate because the form was validated. But that doesn't happen and its because of this lines in yii.activeForm.js
that clearly say that the event afterValidate can only be launched if we are trying to submit the form which we don't because we only want the validation itself.
Currently i have a workaround by playing with the events that looks like this

var validationHandler = function () {
     var form = $('#criar-tarefa-form');
     var data = form.data('yiiActiveForm');
     data.submitting = true;
     data.shouldSubmit = false;
     form.on('afterValidate', handler);
     form.on('beforeSubmit', function () {
               var data = $('#criar-tarefa-form').data('yiiActiveForm');
               if (!data.shouldSubmit) {
                     data.shouldSubmit = true;
                     return false;
               }
     });
     $form.yiiActiveForm('validate', false);
};

but its dirty and unnecessary if the event could be fired after the validation ends.
To solve that problem it could be as simple as

 var updateInputs = function ($form, messages, submitting) {
        var data = $form.data('yiiActiveForm');

        if (data === undefined) {
            return false;
        }

        var errorAttributes = [];
            $.each(data.attributes, function () {
                if (!$(this.input).is(":disabled") && !this.cancelled && updateInput($form, this, messages)) {
                    errorAttributes.push(this);
                }
            });

            $form.trigger(events.afterValidate, [messages, errorAttributes]);

        if (submitting) {
            updateSummary($form, messages);

            if (errorAttributes.length) {
                if (data.settings.scrollToError) {
                    var top = $form.find($.map(errorAttributes, function(attribute) {
                        return attribute.input;
                    }).join(',')).first().closest(':visible').offset().top - data.settings.scrollToErrorOffset;
                    if (top < 0) {
                        top = 0;
                    } else if (top > $(document).height()) {
                        top = $(document).height();
                    }
                    var wtop = $(window).scrollTop();
                    if (top < wtop || top > wtop + $(window).height()) {
                        $(window).scrollTop(top);
                    }
                }
                data.submitting = false;
            } else {
                data.validated = true;
                if (data.submitObject) {
                    applyButtonOptions($form, data.submitObject);
                }
                $form.submit();
                if (data.submitObject) {
                    restoreButtonOptions($form);
                }
            }
        } else {
            $.each(data.attributes, function () {
                if (!this.cancelled && (this.status === 2 || this.status === 3)) {
                    updateInput($form, this, messages);
                }
            });
        }
        submitFinalize($form);
    };

we just pass the errorAttributes setting and the form event before checking if we are submitting. because we want validation only.´

Yii Version 2.0.11.2

Thanks in advance

@samdark samdark added the JS JavaScript related label May 22, 2017
@samdark samdark added this to the 2.0.13 milestone May 22, 2017
@jesseteal
Copy link

I can confirm that lenyy 's fix works. Thank you! I've been wrestling with this problem for too long. I'll post back if I encounter any problems.

@lenyy
Copy link
Author

lenyy commented Jun 23, 2017

@jesseteal np but be careful if you change the updateInputs function from yii because once you composer update and composer finds a new yii version that file probably will be overwritten by it.

@githubjeka
Copy link
Contributor

githubjeka commented Jul 21, 2017

And fix it https://github.com/samdark/yii2-cookbook/blob/master/book/forms-activeform-js.md#trigger-validation-for-the-whole-form

Now to validation form by manually:

If 'enableAjaxValidation' => true, 'enableClientValidation' => false:
$('#form-wizard-step3').yiiActiveForm('validate', true); not
$('#form-wizard-step3').yiiActiveForm('validate', true); works

If 'enableAjaxValidation' => true, 'enableClientValidation' => true:
$('#form-wizard-step3').yiiActiveForm('validate'); not
$('#form-wizard-step3').yiiActiveForm('validate', true); not
to fix should be run
once $('#form-wizard-step3').yiiActiveForm('validate', true);
after $('#form-wizard-step3').yiiActiveForm('validate');
😕

If 'enableAjaxValidation' => false, 'enableClientValidation' => true:
$('#form-wizard-step3').yiiActiveForm('validate'); not
$('#form-wizard-step3').yiiActiveForm('validate', true); not

If 'enableAjaxValidation' => false, 'enableClientValidation' => false:
$('#form-wizard-step3').yiiActiveForm('validate'); works
$('#form-wizard-step3').yiiActiveForm('validate', true); not

@samdark
Copy link
Member

samdark commented Jul 21, 2017

@jesseteal, @lenyy I've re-checked it with a fix and it seems it doesn't work well. It validates field that triggered validation but marks the rest of the fields as valid while they either aren't yet validated or aren't valid.

@samdark samdark removed their assignment Jul 21, 2017
@arogachev arogachev self-assigned this Jul 22, 2017
@lenyy
Copy link
Author

lenyy commented Jul 24, 2017

sorry i forgot to post my form settings. Currently i have

'validateOnChange' => false,
'enableAjaxValidation' => true

for my workaround to work,.

@samdark did you check with the workaround i posted? When i tried i got the desired results, i did not change because when you realeased a new version mine would get overwriten by new version so i opted to stay with bug version and control the events my self

@samdark
Copy link
Member

samdark commented Jul 24, 2017

I did. My comment is about it.

@lenyy
Copy link
Author

lenyy commented Jul 24, 2017

Oh ok sorry, if you need any help just say i can try and test it

@arogachev arogachev changed the title YiiActiveForm not performing validation manually Forced validation in yiiActiveForm do not trigger afterValidate event Jul 29, 2017
@samdark samdark closed this as completed Jul 29, 2017
samdark pushed a commit that referenced this issue Jul 29, 2017
- #14186: Forced validation in `yiiActiveForm` do not trigger `afterValidate` event
- #14510: The state of a form is always "not validated" when using forced validation in `yiiActiveForm`
@lenyy
Copy link
Author

lenyy commented Jul 31, 2017

Thanks @samdark and @arogachev for the fix.
Will try it with next yii release

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
JS JavaScript related type:bug Bug
Projects
None yet
Development

No branches or pull requests

5 participants