yiisoft / yii2

Yii 2: The Fast, Secure and Professional PHP Framework
http://www.yiiframework.com
BSD 3-Clause "New" or "Revised" License
14.23k stars 6.91k forks source link

2.0.16 breaks certain select2 fields validation in active form #17147

Closed kadyrleev closed 4 years ago

kadyrleev commented 5 years ago

Just found that since upgrade 2.0.16 my select2 fields with ajax option are no longer validated. Those with preset data still are. No JS errors in console. Downgraded to 2.0.15.1 and got my forms working again.

rob006 commented 5 years ago

Probably duplicate of https://github.com/yiisoft/yii2/issues/17111

How do you generate AJAX response for select2 widget?

kadyrleev commented 5 years ago

No AJAX calls in my case. The client-side validation is broken somehow so when the form is loaded and you hit "submit" button, those select2 fields (with ajax option) left empty aren't marked as required, while they are and the form is initialized with those fields as required.

rob006 commented 5 years ago

You need to give some code to reproduce this issue.

samdark commented 5 years ago

Closing since there's no way to reproduce it without information on how.

kadyrleev commented 5 years ago

I'm now away from my laptop for 2 weeks, but the code is quite simple: BS ActiveForm widget, inside it a select2 field with ajax option (remote data) and AR respective property rule is set to required. If you're able to reproduce the issue, I'll post the code here later.

samdark commented 5 years ago

select2 isn't part of the framework so it could be added in numerous ways.

kadyrleev commented 5 years ago

Understand that, but no matter which way it's added, the update breaks the validation of that particular field type in active form, which is a part of the framework. The reverse put things back to normal. Had no issues since the start at v2.0.6. I'll post the code to reproduce when back in mid March.

samdark commented 5 years ago

Deal. We'll re-open issue then.

tmendesilva commented 5 years ago

Same problem. I have several select2 input fields on my project and since 2.0.16 framework update validation is not working only for virtual attributes, attributes with database column validation is ok.

samdark commented 5 years ago

@tmendesilva would you please provide a way to reproduce the issue?

tmendesilva commented 5 years ago

Model:

class MyModel extends \yii\db\ActiveRecord {
    public $virtualAttr;
    public function rules() {
        return [
            [
                ['virtualAttr'], 'required'
            ],
        ];
    }
}

View:


$form = ActiveForm::begin([
       'validationUrl' => $validationUrl,
       'enableAjaxValidation' => true,
 ]);
      echo $form->field($model, 'virtualAttr')->widget(kartik\select2\Select2::class, []);
ActiveForm::end();

Obs: same problem without ajax validation too

kadyrleev commented 5 years ago

It didn't work with database column attributes either. At least for me. Select2 from kartik-v too. I moved to another project on Laravel but would appreciate if this bug is fixed.

marianabm commented 5 years ago

I think that the problem is that when select2 uses ajax there is no option element on select element. So, the validation is not working because of this piece of code on validate function (yii.activeForm.js)


if ($input.length && $input[0].tagName.toLowerCase() === 'select') {
    if (!$input[0].options.length) {
        return true;
    } else if (($input[0].options.length === 1) && ($input[0].options[0].value === '')) {
        return true;
    }
}
zeusworkspace commented 5 years ago

Same problem here, no validation when select2 is empty (populates on search by AJAX request). After search and options populated, validation works even by removing select2.

HenryVolkmer commented 4 years ago

not a issue of yii, but a issue of kartik-v/select2. A HTML5 <select> which is required MUST have at least one <option> Element.

A select element with a required attribute and without a multiple attribute, and whose size is “1”, must have a child option element.

https://w3c.github.io/html-reference/select.html

i open a PR @kartik-v /select2

HenryVolkmer commented 4 years ago

fixed with PR https://github.com/kartik-v/yii2-widget-select2/pull/298

samdark commented 4 years ago

Thanks for checking, @HenryVolkmer.

kadyrleev commented 4 years ago

Thanks, @HenryVolkmer !

kadyrleev commented 4 years ago

The fix does not help, unfortunately. At least in my project.

After updating kartik-v/yii2-widget-select2 to v2.1.5 (that includes the proposed fix) and yii2 to the most recent version (2.0.29), I have select2 fields initially having empty values as selected (instead of placeholders as it's supposed to be) and still, no validation working, if I clear the selection.

So reverting back to yii2-widget-select2 to v2.1.4 and yii 2.0.15.1 fixes the problem. We are again where we were.

kartik-v commented 4 years ago

This has been fixed partially with this commit - one needs to still have at least a default data setting with one option - else the new yii form validation will be skipped.

kadyrleev commented 4 years ago

So with no changes made to my code and

the active form select2 fields validation is still broken. Reverting yii back to 2.015.1 fixes the issue.

Here is the snippet of how the field is created in the form:

echo $form ->field($model, 'customer_id') ->widget(Select2::class, [ 'data' => $data, 'theme' => Select2::THEME_BOOTSTRAP, 'options' => [ 'readonly' => !!$source, 'placeholder' => ['id' => -1, 'text' => 'Select company'], ], 'pluginOptions' => [ 'width' => '100%', 'allowClear' => true, 'minimumInputLength' => 3, 'ajax' => [ 'url' => Url::to(['/customer/list']), 'delay' => 250, 'dataType' => 'json', 'data' => new JsExpression('function(params) { return {q:params.term, page:params.page||1}; }') ], ], ]);

It's a required field for the model and it's marked as so if submitted empty with yii 2.0.15.1: image and it passes validation on yii >= 2.0.16 which is wrong.

Maybe I'm missing something 'cause the code is quite old and may be configuration array must be updated. But this is the actual case as described.

Androphin commented 4 years ago

@licanulla You have the same problem with AJAX and the Select2 widget as we do here https://github.com/kartik-v/yii2-widget-select2/pull/298#issuecomment-557086607. There is something broken with yii.activeForm.js and how the selectbox creates option elements that aren't validated.

kadyrleev commented 4 years ago

@Androphin Yes, it's caused by the changes in yii.activeForm.js and still not fixed. Here is the comment from kartik-v: https://github.com/kartik-v/yii2-widget-select2/issues/289#issuecomment-567160614

Previously the code worked as expected: required select2 did not pass the validation if the model fields set as required. I do not think having an extra option beyond the empty one is a good solution though.

buttflattery commented 4 years ago

i second it, the validation does not work with a select2 with ajax, the validation is skipped for the required fields even using the whenClient option. unless you provide a default option like

Select2::class,
            [
                'options' => [
                    'placeholder' => 'Select Campaign',
                    'class' => 'form-control',
                    // 'id' => 'campaign_single',
                    // 'value' => '',
                ],
                'data' => [''],
kadyrleev commented 4 years ago

Still not a fix a this gives you an ungly empty element: image and validation for it still passes.

kadyrleev commented 4 years ago

not a issue of yii, but a issue of kartik-v/select2. A HTML5 <select> which is required MUST have at least one <option> Element.

A select element with a required attribute and without a multiple attribute, and whose size is “1”, must have a child option element.

https://w3c.github.io/html-reference/select.html

i open a PR @kartik-v /select2

The below applies to

The code produced by Select2 widget (without an empty option) appears to be valid: <select id="operation-customer_id" name="Operation[customer_id]" aria-required="true"> according to https://validator.w3.org/ as there is NO required attribute on it and this statement is not true:

image

While with required attribute the markup is not valid: image

The issue must be re-opened as the changes in yii.activeForm.js are breaking a correct validation: https://github.com/kartik-v/yii2-widget-select2/issues/289#issuecomment-533504453

samdark commented 4 years ago

@licanulla any idea about fixing it properly?

kadyrleev commented 4 years ago

@samdark Not yet. I'm currently in a support mode of some of my old projects so will need time to dig into the code but hopefully someone who is actively using yii2 could catch up.

buttflattery commented 4 years ago

Still not a fix a this gives you an ungly empty element: image and validation for it still passes.

@licanulla if the above was in context to what i posted i can share the version numbers but it does not give you an ugly empty element when a placeholder is given and it does not allow you to pass the validation.

image

Here is the complete code block i am using for one of those selects

<?php
        echo
        $form->field(
            $model,
            'campaign_from',
            [
                'template' => '{input}{error}',
            ]
        )->widget(
            Select2::class,
            [
                'options' => [
                    'placeholder' => 'Campaign From',
                    'class' => 'form-control',
                    'id' => 'campaign_from',
                ],
                'data' => [''],
                'theme' => Select2::THEME_BOOTSTRAP,
                'pluginOptions' => [
                    'minimumInputLength' => 3,
                    'allowClear' => true,
                    'ajax' => [
                        'url' => Url::to(['/user/campaign/campaign-listing']),
                        'method' => 'POST',
                        'dataType' => 'json',
                        'data' => new JsExpression(
                            'function(params){
                                let request_params= {
                                    q:params.term,
                                    page:params.page || 1
                                };
                                request_params[yii.getCsrfParam()]=yii.getCsrfToken();
                                return request_params;
                            }'
                        ),
                    ],
                ],
            ]
        )->label(false);
    ?>
Version Details
kartik-v/yii2-widget-select2 v2.1.7
yiisoft/yii2 v2.0.35
OS Windows10
kartik-v commented 4 years ago

I feel the change should be done to yii.activeform.js for the following conditions.

Skipping validation for EMPTY OPTIONS for SELECT inputs must be restricted ONLY for the following conditions (summarizing rules as per W3C validator):

Only for the exclusive above case - the select input MUST have a child option. For all other conditions - the SELECT input can have EMPTY options and the ORIGINAL yii2 validation rules (prior to the new change) MUST BE allowed to run.

samdark commented 4 years ago

@kartik-v sounds about right. Are you into preparing these changes?

kartik-v commented 4 years ago

Will try to raise a PR

kartik-v commented 4 years ago

Submitted PR #18065 to fix this.

kadyrleev commented 4 years ago

@samdark @kartik-v Thank you, guys!