Reputation: 2733
I have an interesting scenario at hand, however I'm not well versed with jQuery validate at the moment.
GOAL: Using the FileAPI, determine the file size of each file to be uploaded in multiple <input type="file" />
controls while also using the jQuery validate plugin, ensuring that the combined total of bytes is not greater than 50Mb. These elements can be dynamically added/deleted.
For the sake of consistency, I'd like this validation to work through the jQuery validator plugin, where the error message will be appended under the last input file control.
From what I understand, adding a method to the validator only verifies one element at a time, so I guess first question, can a single method validate MULTIPLE elements once as opposed to being fired for each element.
Ex.:
<input type="file" name="file1" id="file1" />
<input type="file" name="file2" id="file2" />
<input type="file" name="file3" id="file3" />
<script type="text/javascript">
$(function() {
// Add rule to all elements when document is ready
$('input[type="file"]').rules("add", {
totalFileSize: true
});
});
jQuery.validator.addMethod("totalFileSize", function(value, element) {
// Even if there's 3 input elements, this should only fire once and,
// if totalFileSize > 50Mb, then display error under the last input element
}, "Total file size too large");
</script>
Upvotes: 0
Views: 487
Reputation: 98718
From what I understand, adding a method to the validator only verifies one element at a time, so I guess first question, can a single method validate MULTIPLE elements once as opposed to being fired for each element.
Yes, each element is verified by itself against each rule declared upon it.
No, a single method cannot validate multiple elements at once. The rule/method is declared on each element and then each of these elements are validated against it one at a time.
Edit: I forgot about the skip_or_fill_minimum
and the require_from_group
rules that are part of the additional-methods.js
file. These rules are examples of methods that can evaluate several fields at once. The rule must be declared on each field considered for evaluation, and the groups
option is then used to condense the duplicate messages into one.
Play around with it here: jsfiddle.net/r32vbm8j/
However, these two example rules are fired when the submit button is clicked. In that case, it's not fired once... but fired on each declared field, same as all other rules on the form.
You cannot do this...
$('input[type="file"]').rules("add", {
totalFileSize: true
});
Since the $('input[type="file"]')
selector can represent multiple elements, only the first matching element is attached to .rules()
, and the other matching elements are ignored.
To attach .rules()
to multiple elements requires iteration using a jQuery .each()
.
$('input[type="file"]').each(function() {
$(this).rules("add", {
totalFileSize: true
});
});
EDIT:
The only problem in the end is that
groups
will display all rules assigned to an individual element at a single unified point, whereas I would need to display that one error message for x number of elements while also retaining all other error messages assigned to their respective elements. End result is that I want each of the file inputs to display "File cannot exceed 10MB" as an error message, but have a second validation that checks the sum of all the sizes, "Sum of files cannot exceed 50MB" however that one error message should be singled out, as not to be needlessly repeated.
Employ the showErrors
callback function. This will suppress all individual error messages as long as you leave out the this.defaultShowErrors()
line.
Within the showErrors
function you have access to the following arguments where you can construct your own consolidated or individual messages as you see fit.
errorMap
- Key/value pairs, where the key refers to the name of an input field, values the message to be displayed for that input.
errorList
- An array for all currently validated elements. Contains objects with the following two properties: message
and element
.
$('form').validate({
showErrors: function(errorMap, errorList) {
// parse and display messages as needed
},
....
Upvotes: 1