Closed SillyPhp closed 5 years ago
using with active form and model and the field is set to required with model rules, but on page load even though the field is required its getting submitted on form submit in blank
Cannot reproduce your issue. Can you please check your app code to ensure you are not overwriting the model attributes. You can cross check the demos where this works fine.
It happens to me too..
The attribute has required rule on model but the clientside validation didn't trigger for select2 field.
The client side validation only happens when I change the value.. but if I skip that field and try to submit form I got no validation errors and the form is submitted
I encountered the very same problem and, after some digging, figured out why this happens. Yii ActiveForm validator (yii.activeForm.js) skips validation when encounters select inputs with no options available or with just one option whose value is empty.
A workaround is to add the 'data' option to the widget, so there will be at least one option available at start.
Hello @kartik-v , The conditional validation is not working with select2 on the first-page load. once the form submits the server-side validation adds error to the attribute then it starts working correctly
i am using yii\base\Model
for my form where i have 2 dropdowns
in my model rules, I am using conditional validation like
return [
[
['export_type'], 'required',
],
[
'campaign_single', 'required',
'when' => function ($model) {
return $model->export_type === self::EXPORT_TYPE_SINGLE;
},
'whenClient' => "function(attribute, value){
return ($('#export_type').val() == 'single');
}",
],
];
The difference i have noticed is the on the first page load the default dropdown that is hidden for Select2 looks like below
<select id="campaign_single" class="form-control select2-hidden-accessible" name="ExportSubscribers[campaign_single]" data-s2-options="s2options_6cc131ae" data-krajee-select2="select2_8df6e9a7" style="display:none" data-select2-id="campaign_single" tabindex="-1" aria-hidden="true">
<option value="" data-select2-id="4">Select Campaign</option>
</select>
and once i hit the submit and the form loads with erorrs after page refresh the default dropdown looks like below, which has an extra option added <option value="" selected="" data-select2-id="6"></option>
<select id="campaign_single" class="form-control select2-hidden-accessible" name="ExportSubscribers[campaign_single]" aria-invalid="true" data-s2-options="s2options_6cc131ae" data-krajee-select2="select2_8df6e9a7" style="display:none" data-select2-id="campaign_single" tabindex="-1" aria-hidden="true">
<option value="" data-select2-id="5">Select Campaign</option>
<option value="" selected="" data-select2-id="6"></option>
</select>
@Axhind even if there is one option defined in the select2, the second condition wont allow to validate as it is checking if there is only one option and its value is empty, which means that if you are initializing the select2 with a placeholder
it ant going to work neither adding the data option to the select2 is a workaround when you are using select2 with ajax.
The workaround i have found is to add value
option under the options
option like
'value' => '',
and then it starts working but for select2 single select only and not for the multi-select
@buttflattery yes, as i wrote
or with just one option whose value is empty
so, that goes without saying, the added 'data' option needs to be not a placeholder. Of course this is a viable workaround (and then far from being a solution) only if, as was my case, some values can be made available at start.
@buttflattery i am not fully clear on how the validation is being triggered for your use case and what you are configuring as values for your dropdown and if you have checked cases like @Axhind has mentioned. Check if it works properly for a native HTML select and work up from there
@kartik-v , although i remember that i wrote in about the native drop-down but somehow it is missing in my post, Yes the native dropdown works correctly with the above rules configured.
About the values, the campaign_single
isnt initialized with any data as it is using the ajax option to fetch the data, and the export_type
has only 2 options ['single'=>'Single','multiple'=>'Multiple']
.
The case that Axhind has mentioned is not a workaround that would work for both single and multi-select, although for the single-select adding the value
attribute under the options
option makes it work but not if you are using the multi-select
with multiple=>true
.
I have provided the minimum fields above from the form but i am using a multi-select too which wont fix even if i provide the value
option.
I have left office at the moment so cant add the code right now but will add tomorrow all the relevant code from the form,controller and model that you can run at your end to verify.
@kartik-v Here is the code that can help you reproduce the issue. Before you use the code here are the few things important to compare at your end
Yii Version : 2.0.27 kartik-v/yii2-widgets : v3.4.1 kartik-v/yii2-widget-select2 : v2.1.4
Below is the code for the model and the form the controller code isnt relevant so not adding it. just copy paste the elow code and run it
ExportSubscribers
<?php
namespace frontend\models;
use yii\db\Query;
use yii\base\Model;
class ExportSubscribers extends Model
{
/**
* @var mixed
*/
public $export_type;
/**
* @var mixed
*/
public $campaign_single;
/**
* @var mixed
*/
public $campaign_multiple;
const EXPORT_TYPE_SINGLE = 'single';
const EXPORT_TYPE_MULTIPLE = 'multiple';
/**
* @return mixed
*/
public function rules()
{
return [
[
['export_type'], 'required',
],
[
'campaign_single', 'required',
'when' => function ($model) {
return $model->export_type === self::EXPORT_TYPE_SINGLE;
},
'whenClient' => "function(attribute, value){
return ($('#export_type').val() == '" . self::EXPORT_TYPE_SINGLE . "');
}",
],
[
'campaign_multiple', 'required',
'when' => function ($model) {
return ($model->export_type === self::EXPORT_TYPE_MULTIPLE);
},
'whenClient' => "function(attribute,value){
return ($('#export_type').val() == '" . self::EXPORT_TYPE_MULTIPLE . "');
}",
],
];
}
public function getExportTypes()
{
return [
self::EXPORT_TYPE_SINGLE => 'Single',
self::EXPORT_TYPE_MULTIPLE => 'Multiple',
];
}
public function attributeLabels()
{
return [
'export_type' => 'Export Type',
'campaign_single' => 'Campaign',
'campaign_from' => 'Difference From',
];
}
}
<?php
$js=<<<JS
let EXPORT_CSV = {
updateFormOptions(choice) {
let showFormOptions = {
single() {
$("#row-single").show();
$("#row-multiple").hide();
},
multiple() {
$("#row-single").hide();
$("#row-multiple").show();
}
};
if (showFormOptions.hasOwnProperty(choice)) {
showFormOptions[choice].call();
}
},
};
JS;
$this->registerJs($js,\yii\web\View::POS_READY);
$form = ActiveForm::begin(
[
'id' => 'export-form',
'fieldConfig' => [
'options' => [
'tag' => 'div',
'class' => 'form-group form-float',
],
],
]
);
?>
<div class="row clearfix">
<div class="col-sm-12">
<?php
echo
$form->field(
$model, 'export_type',
[
'template' => '{input}{error}',
]
)->widget(
Select2::class,
[
'data' => $model->getExportTypes(),
'options' => [
'class' => 'form-control',
'id' => 'export_type',
'placeholder' => 'Select Export Type',
],
'theme' => Select2::THEME_BOOTSTRAP,
'pluginOptions' => [
'allowClear' => true,
],
'pluginEvents' => [
"select2:select" => "function(e) { EXPORT_CSV.updateFormOptions(e.params.data.id); }",
],
]
)->label(false);
?>
</div>
</div>
<div class="row clearfix" id="row-single" style="<?php echo ($model->export_type === $model::EXPORT_TYPE_SINGLE ? '' : 'display:none;') ?>">
<div class="col-sm-6">
<?php
echo
$form->field(
$model,
'campaign_single',
[
'template' => '{input}{error}',
]
)->widget(
Select2::class,
[
'options' => [
'placeholder' => 'Select Campaign',
'class' => 'form-control',
'id' => 'campaign_single',
'value' => '',
],
'theme' => Select2::THEME_BOOTSTRAP,
'pluginOptions' => [
'minimumInputLength' => 3,
'allowClear' => true,
'ajax' => [
'url' => Url::to(['/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);
?>
</div>
</div>
<div id="row-multiple" style="<?php echo ($model->export_type !== $model::EXPORT_TYPE_MULTIPLE ? 'display:none;' : '') ?>">
<div class="row clearfix">
<div class="col-sm-6">
<?php
echo
$form->field(
$model,
'campaign_multiple',
[
'template' => '{input}{error}',
]
)->widget(
Select2::class,
[
'options' => [
'multiple => true
'placeholder' => 'Campaign Multiple',
'class' => 'form-control',
'id' => 'campaign_multiple',
'value' => '',
],
'theme' => Select2::THEME_BOOTSTRAP,
'pluginOptions' => [
'minimumInputLength' => 3,
'allowClear' => true,
'ajax' => [
'url' => Url::to(['/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);
?>
</div>
</div>
</div>
<div class="form-group">
<?php echo Html::submitButton('Export', ['class' => 'btn btn-success waves-effect']) ?>
</div>
<?php ActiveForm::end();?>
Hi,
the issue was tracked here too: https://github.com/yiisoft/yii2/issues/17147
Yii2 ignore required <select>
without options because it is no valid HTML.
Have a look at https://w3c.github.io/html-reference/select.html
A select element with a required attribute and without a multiple attribute, and whose size is “1”, must have a child option element. The first child option element of a select element with a required attribute and without a multiple attribute, and whose size is “1”, must have either an empty value attribute, or must have no text content.
The select2 widget should add an empty option, if no Select2::data
was configured.
Fixed via #298 and 9a34ab0
@kartik-v so , do we need to still add the value
attribute under options
or remove it ?
It should do it automatically. Refer commit 9a34ab0.
Yeah i looked into the commit thanks.
Still not working for me: https://github.com/yiisoft/yii2/issues/17147#issuecomment-559954251
Am I missing something in the field config?
It seems the issue is as mentioned by @Axhind in this comment.
This is due to an update to the yii2 form validation script which behaves in a totally different way now and skips select dropdowns with no options OR just one empty option.
The solution workaround is that you need to have at least ONE EXTRA option in your SELECT dropdown beyond the empty value (which is set via placeholder).
Hey, no kartik, its a issue in select2 widget. Please refer (again...) to my PR, which fixing this bug (since 13.Oct.2019).
@HenryVolkmer Thanks for your contribution. Although with your fix and yii >=2.0.16 the problem with form validation is still there, while having yii rolled back to 2.0.15 "fixes" it.
ty for your feedback! Please checkout my latest Version, it should work now. (https://youtu.be/JwCdHIzoTPI)
I found this workaround: $(".select2").on("focusout", function(e){ $('#form-id').yiiActiveForm("validateAttribute", "model-field");});
It looks to me the problem is with yii.activeForm.js, not the widget itself: https://github.com/yiisoft/yii2/issues/17147#issuecomment-633016544
ty for your feedback! Please checkout my latest Version, it should work now. (https://youtu.be/JwCdHIzoTPI)
@HenryVolkmer - this is not a correct fix... it adds another value - #
- to the list of options which one can anyway do on his own by setting data
.
Prerequisites
master
branch of yii2-widget-select2.Steps to reproduce the issue
1. 2. 3.
Expected behavior and actual behavior
When I follow those steps, I see...
I was expecting...
Environment
Browsers
Operating System
Libraries
Isolating the problem