Fix #17147: Fix form attribute validations for empty select inputs

This commit is contained in:
Kartik Visweswaran
2020-08-04 22:17:40 +05:30
committed by GitHub
parent 1ade4993f9
commit cf364f5e00
2 changed files with 50 additions and 41 deletions

View File

@ -4,6 +4,7 @@ Yii Framework 2 Change Log
2.0.37 under development 2.0.37 under development
------------------------ ------------------------
- Bug #17147: Fix form attribute validations for empty select inputs (kartik-v)
- Bug #18171: Change case of column names in SQL query for `findConstraints` to fix MySQL 8 compatibility (darkdef) - Bug #18171: Change case of column names in SQL query for `findConstraints` to fix MySQL 8 compatibility (darkdef)
- Bug #18170: Fix 2.0.36 regression in passing extra console command arguments to the action (darkdef) - Bug #18170: Fix 2.0.36 regression in passing extra console command arguments to the action (darkdef)
- Bug #18182: `yii\db\Expression` was not supported as condition in `ActiveRecord::findOne()` and `ActiveRecord::findAll()` (rhertogh) - Bug #18182: `yii\db\Expression` was not supported as condition in `ActiveRecord::findOne()` and `ActiveRecord::findAll()` (rhertogh)

View File

@ -14,11 +14,13 @@
$.fn.yiiActiveForm = function (method) { $.fn.yiiActiveForm = function (method) {
if (methods[method]) { if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1)); return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else { } else {
$.error('Method ' + method + ' does not exist on jQuery.yiiActiveForm'); if (typeof method === 'object' || !method) {
return false; return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.yiiActiveForm');
return false;
}
} }
}; };
@ -178,14 +180,14 @@
var submitDefer; var submitDefer;
var setSubmitFinalizeDefer = function($form) { var setSubmitFinalizeDefer = function ($form) {
submitDefer = $.Deferred(); submitDefer = $.Deferred();
$form.data('yiiSubmitFinalizePromise', submitDefer.promise()); $form.data('yiiSubmitFinalizePromise', submitDefer.promise());
}; };
// finalize yii.js $form.submit // finalize yii.js $form.submit
var submitFinalize = function($form) { var submitFinalize = function ($form) {
if(submitDefer) { if (submitDefer) {
submitDefer.resolve(); submitDefer.resolve();
submitDefer = undefined; submitDefer = undefined;
$form.removeData('yiiSubmitFinalizePromise'); $form.removeData('yiiSubmitFinalizePromise');
@ -327,15 +329,22 @@
this.$form = $form; this.$form = $form;
var $input = findInput($form, this); var $input = findInput($form, this);
if ($input.is(":disabled")) { if ($input.is(':disabled')) {
return true; return true;
} }
// pass SELECT without options // validate markup for select input
if ($input.length && $input[0].tagName.toLowerCase() === 'select') { if ($input.length && $input[0].tagName.toLowerCase() === 'select') {
if (!$input[0].options.length) { var opts = $input[0].options, isEmpty = !opts || !opts.length, isRequired = $input.attr('required'),
return true; isMultiple = $input.attr('multiple'), size = $input.attr('size') || 1;
} else if (($input[0].options.length === 1) && ($input[0].options[0].value === '')) { // check if valid HTML markup for select input, else return validation as `true`
return true; // https://w3c.github.io/html-reference/select.html
if (isRequired && !isMultiple && parseInt(size, 10) === 1) { // invalid select markup condition
if (isEmpty) { // empty option elements for the select
return true;
}
if (opts[0] && (opts[0].value !== '' && opts[0].text !== '')) { // first option is not empty
return true;
}
} }
} }
this.cancelled = false; this.cancelled = false;
@ -363,7 +372,7 @@
}); });
// ajax validation // ajax validation
$.when.apply(this, deferreds).always(function() { $.when.apply(this, deferreds).always(function () {
// Remove empty message arrays // Remove empty message arrays
for (var i in messages) { for (var i in messages) {
if (0 === messages[i].length) { if (0 === messages[i].length) {
@ -404,13 +413,15 @@
submitFinalize($form); submitFinalize($form);
} }
}); });
} else if (data.submitting) {
// delay callback so that the form can be submitted without problem
window.setTimeout(function () {
updateInputs($form, messages, submitting);
}, 200);
} else { } else {
updateInputs($form, messages, submitting); if (data.submitting) {
// delay callback so that the form can be submitted without problem
window.setTimeout(function () {
updateInputs($form, messages, submitting);
}, 200);
} else {
updateInputs($form, messages, submitting);
}
} }
}); });
}, },
@ -459,9 +470,9 @@
$errorElement = data.settings.validationStateOn === 'input' ? $input : $container; $errorElement = data.settings.validationStateOn === 'input' ? $input : $container;
$errorElement.removeClass( $errorElement.removeClass(
data.settings.validatingCssClass + ' ' + data.settings.validatingCssClass + ' ' +
data.settings.errorCssClass + ' ' + data.settings.errorCssClass + ' ' +
data.settings.successCssClass data.settings.successCssClass
); );
$container.find(this.error).html(''); $container.find(this.error).html('');
}); });
@ -492,7 +503,7 @@
* @param id attribute ID * @param id attribute ID
* @param messages array with error messages * @param messages array with error messages
*/ */
updateAttribute: function(id, messages) { updateAttribute: function (id, messages) {
var attribute = methods.find.call(this, id); var attribute = methods.find.call(this, id);
if (attribute != undefined) { if (attribute != undefined) {
var msg = {}; var msg = {};
@ -518,7 +529,7 @@
} }
if (attribute.validateOnType) { if (attribute.validateOnType) {
$input.on('keyup.yiiActiveForm', function (e) { $input.on('keyup.yiiActiveForm', function (e) {
if ($.inArray(e.which, [16, 17, 18, 37, 38, 39, 40]) !== -1 ) { if ($.inArray(e.which, [16, 17, 18, 37, 38, 39, 40]) !== -1) {
return; return;
} }
if (attribute.value !== getValue($form, attribute)) { if (attribute.value !== getValue($form, attribute)) {
@ -571,7 +582,7 @@
* @param val2 * @param val2
* @returns boolean * @returns boolean
*/ */
var isEqual = function(val1, val2) { var isEqual = function (val1, val2) {
// objects // objects
if (val1 instanceof Object) { if (val1 instanceof Object) {
return isObjectsEqual(val1, val2) return isObjectsEqual(val1, val2)
@ -592,7 +603,7 @@
* @param obj2 * @param obj2
* @returns boolean * @returns boolean
*/ */
var isObjectsEqual = function(obj1, obj2) { var isObjectsEqual = function (obj1, obj2) {
if (!(obj1 instanceof Object) || !(obj2 instanceof Object)) { if (!(obj1 instanceof Object) || !(obj2 instanceof Object)) {
return false; return false;
} }
@ -621,7 +632,7 @@
* @param arr2 * @param arr2
* @returns boolean * @returns boolean
*/ */
var isArraysEqual = function(arr1, arr2) { var isArraysEqual = function (arr1, arr2) {
if (!Array.isArray(arr1) || !Array.isArray(arr2)) { if (!Array.isArray(arr1) || !Array.isArray(arr2)) {
return false; return false;
} }
@ -644,7 +655,7 @@
*/ */
var deferredArray = function () { var deferredArray = function () {
var array = []; var array = [];
array.add = function(callback) { array.add = function (callback) {
this.push(new $.Deferred(callback)); this.push(new $.Deferred(callback));
}; };
return array; return array;
@ -707,10 +718,11 @@
var errorAttributes = [], $input; var errorAttributes = [], $input;
$.each(data.attributes, function () { $.each(data.attributes, function () {
var hasError = (submitting && updateInput($form, this, messages)) || (!submitting && attrHasError($form, this, messages)); var hasError = (submitting && updateInput($form, this, messages)) || (!submitting && attrHasError($form,
this, messages));
$input = findInput($form, this); $input = findInput($form, this);
if (!$input.is(":disabled") && !this.cancelled && hasError) { if (!$input.is(':disabled') && !this.cancelled && hasError) {
errorAttributes.push(this); errorAttributes.push(this);
} }
}); });
@ -721,14 +733,10 @@
updateSummary($form, messages); updateSummary($form, messages);
if (errorAttributes.length) { if (errorAttributes.length) {
if (data.settings.scrollToError) { if (data.settings.scrollToError) {
var top = $form.find($.map(errorAttributes, function(attribute) { var h = $(document).height(), top = $form.find($.map(errorAttributes, function (attribute) {
return attribute.input; return attribute.input;
}).join(',')).first().closest(':visible').offset().top - data.settings.scrollToErrorOffset; }).join(',')).first().closest(':visible').offset().top - data.settings.scrollToErrorOffset;
if (top < 0) { top = top < 0 ? 0 : (top > h ? h : top);
top = 0;
} else if (top > $(document).height()) {
top = $(document).height();
}
var wtop = $(window).scrollTop(); var wtop = $(window).scrollTop();
if (top < wtop || top > wtop + $(window).height()) { if (top < wtop || top > wtop + $(window).height()) {
$(window).scrollTop(top); $(window).scrollTop(top);
@ -809,11 +817,11 @@
$error.html(messages[attribute.id][0]); $error.html(messages[attribute.id][0]);
} }
$errorElement.removeClass(data.settings.validatingCssClass + ' ' + data.settings.successCssClass) $errorElement.removeClass(data.settings.validatingCssClass + ' ' + data.settings.successCssClass)
.addClass(data.settings.errorCssClass); .addClass(data.settings.errorCssClass);
} else { } else {
$error.empty(); $error.empty();
$errorElement.removeClass(data.settings.validatingCssClass + ' ' + data.settings.errorCssClass + ' ') $errorElement.removeClass(data.settings.validatingCssClass + ' ' + data.settings.errorCssClass + ' ')
.addClass(data.settings.successCssClass); .addClass(data.settings.successCssClass);
} }
attribute.value = getValue($form, attribute); attribute.value = getValue($form, attribute);
} }
@ -878,7 +886,7 @@
var $realInput = $input.filter(':checked'); var $realInput = $input.filter(':checked');
if ($realInput.length > 1) { if ($realInput.length > 1) {
var values = []; var values = [];
$realInput.each(function(index) { $realInput.each(function (index) {
values.push($($realInput.get(index)).val()); values.push($($realInput.get(index)).val());
}); });
return values; return values;
@ -909,4 +917,4 @@
$form.find(attribute.input).attr('aria-invalid', hasError ? 'true' : 'false'); $form.find(attribute.input).attr('aria-invalid', hasError ? 'true' : 'false');
} }
} }
})(window.jQuery); })(window.jQuery);