Skip to content

Commit 5e5da5d

Browse files
authored
fix(formvalidation): support native validation, after submit only
Form validation will trigger success even if native form validations are still invalid. This PR respects any native form validation by the browser in addition to the FUI form validation rules Native invalid fields (like required file inputs) are now only shown as error'ed after a form submit has taken place at least once I also fixed a possible double submit when the submit button is not a native submit input.
1 parent edee12d commit 5e5da5d

File tree

3 files changed

+49
-33
lines changed

3 files changed

+49
-33
lines changed

src/definitions/behaviors/form.js

Lines changed: 47 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
initialize: function () {
7878
// settings grabbed at run time
7979
module.get.settings();
80+
$module.addClass(className.initial);
8081
if (methodInvoked) {
8182
if (instance === undefined) {
8283
module.instantiate();
@@ -130,10 +131,13 @@
130131
module.bindEvents();
131132
},
132133

133-
submit: function () {
134+
submit: function (event) {
134135
module.verbose('Submitting form', $module);
135136
submitting = true;
136137
$module.trigger('submit');
138+
if (event) {
139+
event.preventDefault();
140+
}
137141
},
138142

139143
attachEvents: function (selector, action) {
@@ -159,6 +163,7 @@
159163
.on('click' + eventNamespace, selector.reset, module.reset)
160164
.on('click' + eventNamespace, selector.clear, module.clear)
161165
;
166+
$field.on('invalid' + eventNamespace, module.event.field.invalid);
162167
if (settings.keyboardShortcuts) {
163168
$module.on('keydown' + eventNamespace, selector.field, module.event.field.keydown);
164169
}
@@ -274,8 +279,12 @@
274279
var
275280
allValid = true
276281
;
277-
$.each(validation, function (fieldName, field) {
278-
if (!module.validate.field(field, fieldName, true)) {
282+
$field.each(function (index, el) {
283+
var $el = $(el),
284+
validation = module.get.validation($el) || {},
285+
identifier = module.get.identifier(validation, $el)
286+
;
287+
if (!module.validate.field(validation, identifier, true)) {
279288
allValid = false;
280289
}
281290
});
@@ -431,25 +440,27 @@
431440
if (!event.ctrlKey && key === keyCode.enter && isInput && !isInDropdown && !isCheckbox) {
432441
if (!keyHeldDown) {
433442
$field.one('keyup' + eventNamespace, module.event.field.keyup);
434-
module.submit();
443+
module.submit(event);
435444
module.debug('Enter pressed on input submitting form');
436-
event.preventDefault();
437445
}
438446
keyHeldDown = true;
439447
}
440448
},
441449
keyup: function () {
442450
keyHeldDown = false;
443451
},
452+
invalid: function (event) {
453+
event.preventDefault();
454+
},
444455
blur: function (event) {
445456
var
446457
$field = $(this),
447-
$fieldGroup = $field.closest($group),
448-
validationRules = module.get.validation($field)
458+
validationRules = module.get.validation($field) || {},
459+
identifier = module.get.identifier(validationRules, $field)
449460
;
450-
if (validationRules && (settings.on === 'blur' || ($fieldGroup.hasClass(className.error) && settings.revalidate))) {
461+
if (settings.on === 'blur' || (!$module.hasClass(className.initial) && settings.revalidate)) {
451462
module.debug('Revalidating field', $field, validationRules);
452-
module.validate.field(validationRules);
463+
module.validate.field(validationRules, identifier);
453464
if (!settings.inline) {
454465
module.validate.form(false, true);
455466
}
@@ -458,14 +469,14 @@
458469
change: function (event) {
459470
var
460471
$field = $(this),
461-
$fieldGroup = $field.closest($group),
462-
validationRules = module.get.validation($field)
472+
validationRules = module.get.validation($field) || {},
473+
identifier = module.get.identifier(validationRules, $field)
463474
;
464-
if (validationRules && (settings.on === 'change' || ($fieldGroup.hasClass(className.error) && settings.revalidate))) {
475+
if (settings.on === 'change' || (!$module.hasClass(className.initial) && settings.revalidate)) {
465476
clearTimeout(module.timer);
466477
module.timer = setTimeout(function () {
467478
module.debug('Revalidating field', $field, validationRules);
468-
module.validate.field(validationRules);
479+
module.validate.field(validationRules, identifier);
469480
if (!settings.inline) {
470481
module.validate.form(false, true);
471482
}
@@ -531,6 +542,9 @@
531542

532543
return fullFields;
533544
},
545+
identifier: function (validation, $el) {
546+
return validation.identifier || $el.attr('id') || $el.attr('name') || $el.data(metadata.validate);
547+
},
534548
prompt: function (rule, field) {
535549
var
536550
ruleName = module.get.ruleName(rule),
@@ -974,7 +988,7 @@
974988
$message.empty();
975989
},
976990
states: function () {
977-
$module.removeClass(className.error).removeClass(className.success);
991+
$module.removeClass(className.error).removeClass(className.success).addClass(className.initial);
978992
if (!settings.inline) {
979993
module.remove.errors();
980994
}
@@ -1211,7 +1225,7 @@
12111225
return rule.type === 'empty';
12121226
}) !== 0
12131227
: false,
1214-
identifier = validation.identifier || $el.attr('id') || $el.attr('name') || $el.data(metadata.validate)
1228+
identifier = module.get.identifier(validation, $el)
12151229
;
12161230
if (isRequired && !isDisabled && !hasEmptyRule && identifier !== undefined) {
12171231
if (isCheckbox) {
@@ -1243,7 +1257,7 @@
12431257
if (keyHeldDown) {
12441258
return false;
12451259
}
1246-
1260+
$module.removeClass(className.initial);
12471261
// reset errors
12481262
formErrors = [];
12491263
if (module.determine.isValid()) {
@@ -1315,23 +1329,31 @@
13151329
? module.get.field(field.depends)
13161330
: false,
13171331
fieldValid = true,
1318-
fieldErrors = []
1332+
fieldErrors = [],
1333+
isDisabled = $field.filter(':not(:disabled)').length === 0,
1334+
validationMessage = $field[0].validationMessage
13191335
;
13201336
if (!field.identifier) {
13211337
module.debug('Using field name as identifier', identifier);
13221338
field.identifier = identifier;
13231339
}
1324-
var isDisabled = $field.filter(':not(:disabled)').length === 0;
1340+
if (validationMessage) {
1341+
module.debug('Field is natively invalid', identifier);
1342+
fieldErrors.push(validationMessage);
1343+
fieldValid = false;
1344+
if (showErrors) {
1345+
$field.closest($group).addClass(className.error);
1346+
}
1347+
} else if (showErrors) {
1348+
$field.closest($group).removeClass(className.error);
1349+
}
13251350
if (isDisabled) {
13261351
module.debug('Field is disabled. Skipping', identifier);
13271352
} else if (field.optional && module.is.blank($field)) {
13281353
module.debug('Field is optional and blank. Skipping', identifier);
13291354
} else if (field.depends && module.is.empty($dependsField)) {
13301355
module.debug('Field depends on another value that is not present or empty. Skipping', $dependsField);
13311356
} else if (field.rules !== undefined) {
1332-
if (showErrors) {
1333-
$field.closest($group).removeClass(className.error);
1334-
}
13351357
$.each(field.rules, function (index, rule) {
13361358
if (module.has.field(identifier)) {
13371359
var invalidFields = module.validate.rule(field, rule, true) || [];
@@ -1348,7 +1370,7 @@
13481370
}
13491371
if (fieldValid) {
13501372
if (showErrors) {
1351-
module.remove.prompt(identifier, fieldErrors);
1373+
module.remove.prompt(identifier);
13521374
settings.onValid.call($field);
13531375
}
13541376
} else {
@@ -1638,8 +1660,8 @@
16381660
isExactly: '{name} must be exactly "{ruleValue}"',
16391661
not: '{name} cannot be set to "{ruleValue}"',
16401662
notExactly: '{name} cannot be set to exactly "{ruleValue}"',
1641-
contain: '{name} must contain "{ruleValue}"',
1642-
containExactly: '{name} must contain exactly "{ruleValue}"',
1663+
contains: '{name} must contain "{ruleValue}"',
1664+
containsExactly: '{name} must contain exactly "{ruleValue}"',
16431665
doesntContain: '{name} cannot contain "{ruleValue}"',
16441666
doesntContainExactly: '{name} cannot contain exactly "{ruleValue}"',
16451667
minLength: '{name} must be at least {ruleValue} characters',
@@ -1673,6 +1695,7 @@
16731695
},
16741696

16751697
className: {
1698+
initial: 'initial',
16761699
error: 'error',
16771700
label: 'ui basic red pointing prompt label',
16781701
pressed: 'down',

src/definitions/collections/form.less

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -585,14 +585,7 @@
585585
box-shadow: @formStates[@@state][boxShadow];
586586
}
587587
& when (@state=error) and (@variationFormInvalid) {
588-
.ui.form .field input:not(:placeholder-shown):invalid {
589-
color: @c;
590-
background: @bg;
591-
border-color: @formStates[@@state][borderColor];
592-
border-radius: @formStates[@@state][borderRadius];
593-
box-shadow: @formStates[@@state][boxShadow];
594-
}
595-
.ui.form .field input:not(:-ms-input-placeholder):invalid when (@supportIE) {
588+
.ui.form:not(.initial) .field input:invalid {
596589
color: @c;
597590
background: @bg;
598591
border-color: @formStates[@@state][borderColor];

src/themes/default/globals/variation.variables

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@
127127
@variationInputDisabled: true;
128128
@variationInputInverted: true;
129129
@variationInputStates: @variationAllStates;
130-
@variationInputInvalid: true;
130+
@variationInputInvalid: false;
131131
@variationInputTransparent: true;
132132
@variationInputCorner: true;
133133
@variationInputLoading: true;

0 commit comments

Comments
 (0)