Skip to content

Commit 3b0a796

Browse files
authored
feat(formvalidation): support object list in add errors
This PR fixes formvalidation and supports named objects as errors for the add errors behavior. This will either create individual prompts when inline:true or provide them as before via central error message box. But will support to put the field name infront. also fetches falsy values for "errors" as well now tries to get the field label for match and different rules centralizes the "get value" which was used inside match/different rules twice and did not check for non standard inputs like dropdown, calender or radio reuse / centralize /simplfy field selector given an non name identifier (such as id) to the "get value" behavior (was not working if id!=name) init a select-dropdown support native checkboxes
1 parent 6ae4c9d commit 3b0a796

File tree

1 file changed

+99
-91
lines changed

1 file changed

+99
-91
lines changed

src/definitions/behaviors/form.js

Lines changed: 99 additions & 91 deletions
Original file line numberDiff line numberDiff line change
@@ -193,7 +193,7 @@
193193
$prompt = $fieldGroup.find(selector.prompt),
194194
$calendar = $field.closest(selector.uiCalendar),
195195
defaultValue = $field.data(metadata.defaultValue) || '',
196-
isCheckbox = $element.is(selector.uiCheckbox),
196+
isCheckbox = $field.is(selector.checkbox),
197197
isDropdown = $element.is(selector.uiDropdown) && module.can.useElement('dropdown'),
198198
isCalendar = $calendar.length > 0 && module.can.useElement('calendar'),
199199
isErrored = $fieldGroup.hasClass(className.error)
@@ -227,7 +227,7 @@
227227
$calendar = $field.closest(selector.uiCalendar),
228228
$prompt = $fieldGroup.find(selector.prompt),
229229
defaultValue = $field.data(metadata.defaultValue),
230-
isCheckbox = $element.is(selector.uiCheckbox),
230+
isCheckbox = $field.is(selector.checkbox),
231231
isDropdown = $element.is(selector.uiDropdown) && module.can.useElement('dropdown'),
232232
isCalendar = $calendar.length > 0 && module.can.useElement('calendar'),
233233
isErrored = $fieldGroup.hasClass(className.error)
@@ -244,7 +244,7 @@
244244
module.verbose('Resetting dropdown value', $element, defaultValue);
245245
$element.dropdown('restore defaults', true);
246246
} else if (isCheckbox) {
247-
module.verbose('Resetting checkbox value', $element, defaultValue);
247+
module.verbose('Resetting checkbox value', $field, defaultValue);
248248
$field.prop('checked', defaultValue);
249249
} else if (isCalendar) {
250250
$calendar.calendar('set date', defaultValue);
@@ -533,8 +533,6 @@
533533
: rule.prompt || settings.prompt[ruleName] || settings.text.unspecifiedRule,
534534
requiresValue = prompt.search('{value}') !== -1,
535535
requiresName = prompt.search('{name}') !== -1,
536-
$label,
537-
name,
538536
parts,
539537
suffixPrompt
540538
;
@@ -551,15 +549,14 @@
551549
prompt = prompt.replace(/{min}/g, parts[0]);
552550
prompt = prompt.replace(/{max}/g, parts[1]);
553551
}
552+
if (ancillary && ['match', 'different'].indexOf(ruleName) >= 0) {
553+
prompt = prompt.replace(/{ruleValue}/g, module.get.fieldLabel(ancillary, true));
554+
}
554555
if (requiresValue) {
555556
prompt = prompt.replace(/{value}/g, $field.val());
556557
}
557558
if (requiresName) {
558-
$label = $field.closest(selector.group).find('label').eq(0);
559-
name = $label.length === 1
560-
? $label.text()
561-
: $field.prop('placeholder') || settings.text.unspecifiedField;
562-
prompt = prompt.replace(/{name}/g, name);
559+
prompt = prompt.replace(/{name}/g, module.get.fieldLabel($field));
563560
}
564561
prompt = prompt.replace(/{identifier}/g, field.identifier);
565562
prompt = prompt.replace(/{ruleValue}/g, ancillary);
@@ -599,7 +596,7 @@
599596
// refresh selector cache
600597
(instance || module).refresh();
601598
},
602-
field: function (identifier) {
599+
field: function (identifier, strict) {
603600
module.verbose('Finding field with identifier', identifier);
604601
identifier = module.escape.string(identifier);
605602
var t;
@@ -621,18 +618,29 @@
621618
}
622619
module.error(error.noField.replace('{identifier}', identifier));
623620

624-
return $('<input/>');
621+
return strict ? $() : $('<input/>');
625622
},
626-
fields: function (fields) {
623+
fields: function (fields, strict) {
627624
var
628625
$fields = $()
629626
;
630627
$.each(fields, function (index, name) {
631-
$fields = $fields.add(module.get.field(name));
628+
$fields = $fields.add(module.get.field(name, strict));
632629
});
633630

634631
return $fields;
635632
},
633+
fieldLabel: function (identifier, useIdAsFallback) {
634+
var $field = typeof identifier === 'string'
635+
? module.get.field(identifier)
636+
: identifier,
637+
$label = $field.closest(selector.group).find('label').eq(0)
638+
;
639+
640+
return $label.length === 1
641+
? $label.text()
642+
: $field.prop('placeholder') || (useIdAsFallback ? identifier : settings.text.unspecifiedField);
643+
},
636644
validation: function ($field) {
637645
var
638646
fieldValidation,
@@ -655,20 +663,22 @@
655663

656664
return fieldValidation || false;
657665
},
658-
value: function (field) {
666+
value: function (field, strict) {
659667
var
660668
fields = [],
661-
results
669+
results,
670+
resultKeys
662671
;
663672
fields.push(field);
664-
results = module.get.values.call(element, fields);
673+
results = module.get.values.call(element, fields, strict);
674+
resultKeys = Object.keys(results);
665675

666-
return results[field];
676+
return resultKeys.length > 0 ? results[resultKeys[0]] : undefined;
667677
},
668-
values: function (fields) {
678+
values: function (fields, strict) {
669679
var
670-
$fields = Array.isArray(fields)
671-
? module.get.fields(fields)
680+
$fields = Array.isArray(fields) && fields.length > 0
681+
? module.get.fields(fields, strict)
672682
: $field,
673683
values = {}
674684
;
@@ -786,16 +796,8 @@
786796

787797
field: function (identifier) {
788798
module.verbose('Checking for existence of a field with identifier', identifier);
789-
identifier = module.escape.string(identifier);
790-
if (typeof identifier !== 'string') {
791-
module.error(error.identifier, identifier);
792-
}
793799

794-
return (
795-
$field.filter('#' + identifier).length > 0
796-
|| $field.filter('[name="' + identifier + '"]').length > 0
797-
|| $field.filter('[data-' + metadata.validate + '="' + identifier + '"]').length > 0
798-
);
800+
return module.get.field(identifier, true).length > 0;
799801
},
800802

801803
},
@@ -819,6 +821,22 @@
819821
},
820822
},
821823

824+
checkErrors: function (errors, internal) {
825+
if (!errors || errors.length === 0) {
826+
if (!internal) {
827+
module.error(settings.error.noErrorMessage);
828+
}
829+
830+
return false;
831+
}
832+
if (!internal) {
833+
errors = typeof errors === 'string'
834+
? [errors]
835+
: errors;
836+
}
837+
838+
return errors;
839+
},
822840
add: {
823841
// alias
824842
rule: function (name, rules) {
@@ -862,15 +880,16 @@
862880
module.refreshEvents();
863881
},
864882
prompt: function (identifier, errors, internal) {
883+
errors = module.checkErrors(errors);
884+
if (errors === false) {
885+
return;
886+
}
865887
var
866888
$field = module.get.field(identifier),
867889
$fieldGroup = $field.closest($group),
868890
$prompt = $fieldGroup.children(selector.prompt),
869891
promptExists = $prompt.length > 0
870892
;
871-
errors = typeof errors === 'string'
872-
? [errors]
873-
: errors;
874893
module.verbose('Adding field error state', identifier);
875894
if (!internal) {
876895
$fieldGroup
@@ -903,11 +922,40 @@
903922
}
904923
},
905924
errors: function (errors) {
925+
errors = module.checkErrors(errors);
926+
if (errors === false) {
927+
return;
928+
}
906929
module.debug('Adding form error messages', errors);
907930
module.set.error();
908-
$message
909-
.html(settings.templates.error(errors))
931+
var customErrors = [],
932+
tempErrors
910933
;
934+
if ($.isPlainObject(errors)) {
935+
$.each(Object.keys(errors), function (i, id) {
936+
if (module.checkErrors(errors[id], true) !== false) {
937+
if (settings.inline) {
938+
module.add.prompt(id, errors[id]);
939+
} else {
940+
tempErrors = module.checkErrors(errors[id]);
941+
if (tempErrors !== false) {
942+
$.each(tempErrors, function (index, tempError) {
943+
customErrors.push(settings.prompt.addErrors
944+
.replace(/{name}/g, module.get.fieldLabel(id))
945+
.replace(/{error}/g, tempError));
946+
});
947+
}
948+
}
949+
}
950+
});
951+
} else {
952+
customErrors = errors;
953+
}
954+
if (customErrors.length > 0) {
955+
$message
956+
.html(settings.templates.error(customErrors))
957+
;
958+
}
911959
},
912960
},
913961

@@ -1012,15 +1060,19 @@
10121060
$el = $(el),
10131061
$parent = $el.parent(),
10141062
isCheckbox = $el.filter(selector.checkbox).length > 0,
1015-
isDropdown = $parent.is(selector.uiDropdown) && module.can.useElement('dropdown'),
1016-
$calendar = $el.closest(selector.uiCalendar),
1017-
isCalendar = $calendar.length > 0 && module.can.useElement('calendar'),
1063+
isDropdown = ($parent.is(selector.uiDropdown) || $el.is(selector.uiDropdown)) && module.can.useElement('dropdown'),
1064+
$calendar = $el.closest(selector.uiCalendar),
1065+
isCalendar = $calendar.length > 0 && module.can.useElement('calendar'),
10181066
value = isCheckbox
10191067
? $el.is(':checked')
10201068
: $el.val()
10211069
;
10221070
if (isDropdown) {
1023-
$parent.dropdown('save defaults');
1071+
if ($parent.is(selector.uiDropdown)) {
1072+
$parent.dropdown('save defaults');
1073+
} else {
1074+
$el.dropdown('save defaults');
1075+
}
10241076
} else if (isCalendar) {
10251077
$calendar.calendar('refresh');
10261078
}
@@ -1320,7 +1372,7 @@
13201372
? String(value + '').trim()
13211373
: String(value + ''));
13221374

1323-
return ruleFunction.call(field, value, ancillary, $module);
1375+
return ruleFunction.call(field, value, ancillary, module);
13241376
}
13251377
;
13261378
if (!isFunction(ruleFunction)) {
@@ -1581,7 +1633,7 @@
15811633
notExactly: '{name} cannot be set to exactly "{ruleValue}"',
15821634
contain: '{name} must contain "{ruleValue}"',
15831635
containExactly: '{name} must contain exactly "{ruleValue}"',
1584-
doesntContain: '{name} cannot contain "{ruleValue}"',
1636+
doesntContain: '{name} cannot contain "{ruleValue}"',
15851637
doesntContainExactly: '{name} cannot contain exactly "{ruleValue}"',
15861638
minLength: '{name} must be at least {ruleValue} characters',
15871639
exactLength: '{name} must be exactly {ruleValue} characters',
@@ -1592,6 +1644,7 @@
15921644
minCount: '{name} must have at least {ruleValue} choices',
15931645
exactCount: '{name} must have exactly {ruleValue} choices',
15941646
maxCount: '{name} must have {ruleValue} or less choices',
1647+
addErrors: '{name}: {error}',
15951648
},
15961649

15971650
selector: {
@@ -1620,11 +1673,11 @@
16201673
},
16211674

16221675
error: {
1623-
identifier: 'You must specify a string identifier for each field',
16241676
method: 'The method you called is not defined.',
16251677
noRule: 'There is no rule matching the one you specified',
16261678
noField: 'Field identifier {identifier} not found',
16271679
noElement: 'This module requires ui {element}',
1680+
noErrorMessage: 'No error message provided',
16281681
},
16291682

16301683
templates: {
@@ -1881,62 +1934,17 @@
18811934
},
18821935

18831936
// matches another field
1884-
match: function (value, identifier, $module) {
1885-
var
1886-
matchingValue,
1887-
matchingElement
1888-
;
1889-
matchingElement = $module.find('[data-validate="' + identifier + '"]');
1890-
if (matchingElement.length > 0) {
1891-
matchingValue = matchingElement.val();
1892-
} else {
1893-
matchingElement = $module.find('#' + identifier);
1894-
if (matchingElement.length > 0) {
1895-
matchingValue = matchingElement.val();
1896-
} else {
1897-
matchingElement = $module.find('[name="' + identifier + '"]');
1898-
if (matchingElement.length > 0) {
1899-
matchingValue = matchingElement.val();
1900-
} else {
1901-
matchingElement = $module.find('[name="' + identifier + '[]"]');
1902-
if (matchingElement.length > 0) {
1903-
matchingValue = matchingElement;
1904-
}
1905-
}
1906-
}
1907-
}
1937+
match: function (value, identifier, module) {
1938+
var matchingValue = module.get.value(identifier, true);
19081939

19091940
return matchingValue !== undefined
19101941
? value.toString() === matchingValue.toString()
19111942
: false;
19121943
},
19131944

19141945
// different than another field
1915-
different: function (value, identifier, $module) {
1916-
// use either id or name of field
1917-
var
1918-
matchingValue,
1919-
matchingElement
1920-
;
1921-
matchingElement = $module.find('[data-validate="' + identifier + '"]');
1922-
if (matchingElement.length > 0) {
1923-
matchingValue = matchingElement.val();
1924-
} else {
1925-
matchingElement = $module.find('#' + identifier);
1926-
if (matchingElement.length > 0) {
1927-
matchingValue = matchingElement.val();
1928-
} else {
1929-
matchingElement = $module.find('[name="' + identifier + '"]');
1930-
if (matchingElement.length > 0) {
1931-
matchingValue = matchingElement.val();
1932-
} else {
1933-
matchingElement = $module.find('[name="' + identifier + '[]"]');
1934-
if (matchingElement.length > 0) {
1935-
matchingValue = matchingElement;
1936-
}
1937-
}
1938-
}
1939-
}
1946+
different: function (value, identifier, module) {
1947+
var matchingValue = module.get.value(identifier, true);
19401948

19411949
return matchingValue !== undefined
19421950
? value.toString() !== matchingValue.toString()

0 commit comments

Comments
 (0)