Skip to content

Commit

Permalink
fixed #1660 #1593
Browse files Browse the repository at this point in the history
  • Loading branch information
danialfarid committed Aug 23, 2016
1 parent 2e3b5bf commit 003b1ef
Show file tree
Hide file tree
Showing 9 changed files with 405 additions and 197 deletions.
8 changes: 5 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ At least one of the `ngf-select` or `ngf-drop` are mandatory for the plugin to l
// called when files are selected, dropped, or cleared
ng-model="myFiles" // binds the valid selected/dropped file or files to the scope model
// could be an array or single file depending on ngf-multiple and ngf-keep values.
ng-model-options="{updateOn: 'change click drop dropUrl paste', allowInvalid: false, debounce: 0}"
ngf-model-options="{updateOn: 'change click drop dropUrl paste', allowInvalid: false, debounce: 0}"
// updateOn could be used to disable resetting on click, or updating on paste, browser image drop, etc.
// allowInvalid default is false could allow invalid files in the model
// debouncing will postpone model update (miliseconds). See angular ng-model-options for more details.
Expand Down Expand Up @@ -225,7 +225,7 @@ At least one of the `ngf-select` or `ngf-drop` are mandatory for the plugin to l
// validate as form.file.$error.maxSize=true and file.$error='maxSize'
// ngf-max-total-size is for multiple file select and validating the total size of all files.
ngf-min-height, ngf-max-height, ngf-min-width, ngf-max-width="1000" in pixels only images
// validate error name: maxHeight
// validate error names: minHeight, maxHeight, minWidth, maxWidth
ngf-ratio="8:10,1.6" // list of comma separated valid aspect ratio of images in float or 2:3 format
// validate error name: ratio
ngf-min-ratio, ngf-max-ratio="8:10" // min or max allowed aspect ratio for the image.
Expand All @@ -246,6 +246,8 @@ At least one of the `ngf-select` or `ngf-drop` are mandatory for the plugin to l
ngf-validate-force="boolean" // default false, if true file.$error will be set if the dimension or duration
// values for validations cannot be calculated for example image load error or unsupported video by the browser.
// by default it would assume the file is valid if the duration or dimension cannot be calculated by the browser.
ngf-ignore-invalid="'pattern, maxSize'" // ignore the files that fail the specified validations.
// They will just be ignored and won't show up in ngf-model-invalid or make the form invalid.
>Upload/Drop</div>
Expand Down Expand Up @@ -408,7 +410,7 @@ you can access the value of the validation using `myForm.myFileInputName.$error.
for example `form.file.$error.pattern`.
If multiple file selection is allowed you can specify `ngf-model-invalid="invalidFiles"` to assing the invalid files to
a model and find the error of each individual file with `file.$error` and description of it with `file.$errorParam`.
You can use angular ng-model-options to allow invalid files to be set to the ng-model `ng-model-options="{allowInvalid: true}"`.
You can use angular ngf-model-options to allow invalid files to be set to the ng-model `ngf-model-options="{allowInvalid: true}"`.

**Upload multiple files**: Only for HTML5 FormData browsers (not IE8-9) you have an array of files or more than one file in your `data` to
send them all in one request . Non-html5 browsers due to flash limitation will upload each file one by one in a separate request.
Expand Down
12 changes: 10 additions & 2 deletions demo/src/main/webapp/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,6 @@ <h3>
<div>
<form name="myForm">
<fieldset>
aaaa{{d}}
<legend>Upload on form submit</legend>
Username: <input type="text" name="userName" ng-model="username" size="39" required>
<i ng-show="myForm.userName.$error.required">*required</i><br>
Expand Down Expand Up @@ -100,6 +99,9 @@ <h3>
ngf-duration="durationFn($file, $duration)"
ngf-keep="keepDistinct ? 'distinct' : keep"
ngf-fix-orientation="orientation"
ngf-max-files="maxFiles"
ngf-ignore-invalid="ignoreInvalid"
ngf-run-all-validations="runAllValidations"
ngf-allow-dir="allowDir" class="drop-box" ngf-drop-available="dropAvailable">Select File
<span ng-show="dropAvailable"> or Drop File</span>
</div>
Expand All @@ -117,6 +119,9 @@ <h3>
ngf-keep="keepDistinct ? 'distinct' : keep"
ngf-enable-firefox-paste="true"
ngf-fix-orientation="orientation"
ngf-max-files="maxFiles"
ngf-ignore-invalid="ignoreInvalid"
ngf-run-all-validations="runAllValidations"
ngf-allow-dir="allowDir" class="drop-box" ng-show="dropAvailable">
<span>Paste or Drop Image from browser</span></div>
</div>
Expand All @@ -131,6 +136,8 @@ <h3>
<label>ngf-resize-if: <input type="text" size="43" ng-model="resizeIf"></label><br/>
<label>ngf-dimensions: <input type="text" size="43" ng-model="dimensions"></label><br/>
<label>ngf-duration: <input type="text" size="43" ng-model="duration"></label><br/>
<label>ngf-max-files: <input type="text" size="43" ng-model="maxFiles"></label><br/>
<label>ngf-ignore-invalid: <input type="text" size="43" ng-model="ignoreInvalid"></label><br/>
<label><input type="checkbox" ng-model="multiple">ngf-multiple (allow multiple files)</label>
<label><input type="checkbox" ng-model="disabled">ng-disabled</label><br/>
<label><input type="checkbox" ng-model="allowDir">ngf-allow-dir (allow directory drop Chrome
Expand All @@ -140,6 +147,7 @@ <h3>
<label><input type="checkbox" ng-model="keepDistinct">ngf-keep="distinct" (do not allow
duplicates)</label><br/>
<label><input type="checkbox" ng-model="orientation">ngf-fix-orientation (for exif jpeg files)</label><br/>
<label><input type="checkbox" ng-model="runAllValidations">ngf-run-all-validations</label><br/>
<label>Upload resumable chunk size: <input type="text" ng-model="chunkSize"></label><br/>
</div>

Expand Down Expand Up @@ -191,7 +199,7 @@ <h3>
</div>
</li>
<li class="sel-file" ng-repeat="f in invalidFiles">
<div>Invalid File: {{f.$error}} {{f.$errorParam}}, {{f.name}} - size: {{f.size}}B - type:
<div>Invalid File: {{f.$errorMessages}} {{f.$errorParam}}, {{f.name}} - size: {{f.size}}B - type:
{{f.type}}
</div>
</li>
Expand Down
114 changes: 76 additions & 38 deletions demo/src/main/webapp/js/ng-file-upload-all.js
Original file line number Diff line number Diff line change
Expand Up @@ -1018,18 +1018,6 @@ ngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadE
return angular.isArray(v) ? v : [v];
}

function separateInvalids() {
valids = [];
invalids = [];
angular.forEach(allNewFiles, function (file) {
if (file.$error) {
invalids.push(file);
} else {
valids.push(file);
}
});
}

function resizeAndUpdate() {
function updateModel() {
$timeout(function () {
Expand All @@ -1041,10 +1029,12 @@ ngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadE

resize(validateAfterResize ? allNewFiles : valids, attr, scope).then(function () {
if (validateAfterResize) {
upload.validate(allNewFiles, prevValidFiles.length, ngModel, attr, scope).then(function () {
separateInvalids();
updateModel();
});
upload.validate(allNewFiles, prevValidFiles.length, ngModel, attr, scope)
.then(function (validationResult) {
valids = validationResult.validsFiles;
invalids = validationResult.invalidsFiles;
updateModel();
});
} else {
updateModel();
}
Expand Down Expand Up @@ -1080,12 +1070,14 @@ ngFileUpload.service('Upload', ['$parse', '$timeout', '$compile', '$q', 'UploadE
var validateAfterResize = upload.attrGetter('ngfValidateAfterResize', attr, scope);

var options = upload.attrGetter('ngfModelOptions', attr, scope);
upload.validate(allNewFiles, prevValidFiles.length, ngModel, attr, scope).then(function () {
upload.validate(allNewFiles, prevValidFiles.length, ngModel, attr, scope)
.then(function (validationResult) {
if (noDelay) {
update(allNewFiles, [], files, dupFiles, isSingleModel);
} else {
if ((!options || !options.allowInvalid) && !validateAfterResize) {
separateInvalids();
valids = validationResult.validFiles;
invalids = validationResult.invalidFiles;
} else {
valids = allNewFiles;
}
Expand Down Expand Up @@ -1717,11 +1709,15 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct
return upload.attrGetter(name, attr, scope, params);
};

var ignoredErrors = (upload.attrGetter('ngfIgnoreInvalid', attr, scope) || '').split(' ');
var runAllValidation = upload.attrGetter('ngfRunAllValidations', attr, scope);

if (files == null || files.length === 0) {
return upload.emptyPromise(ngModel);
}

files = files.length === undefined ? [files] : files.slice(0);
var invalidFiles = [];

function validateSync(name, validationName, fn) {
if (files) {
Expand All @@ -1732,10 +1728,19 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct
var val = upload.getValidationAttr(attr, scope, name, validationName, file);
if (val != null) {
if (!fn(file, val, i)) {
file.$error = name;
(file.$errorMessages = (file.$errorMessages || {}))[name] = true;
file.$errorParam = val;
files.splice(i, 1);
if (ignoredErrors.indexOf(name) === -1) {
file.$error = name;
(file.$errorMessages = (file.$errorMessages || {}))[name] = true;
file.$errorParam = val;
if (invalidFiles.indexOf(file) === -1) {
invalidFiles.push(file);
}
if (!runAllValidation) {
files.splice(i, 1);
}
} else {
files.splice(i, 1);
}
valid = false;
}
}
Expand All @@ -1747,9 +1752,6 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct
}
}

validateSync('maxFiles', null, function (file, val, i) {
return prevLength + i < val;
});
validateSync('pattern', null, upload.validatePattern);
validateSync('minSize', 'size.min', function (file, val) {
return file.size + 0.1 >= upload.translateScalars(val);
Expand All @@ -1776,22 +1778,42 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct
}

function validateAsync(name, validationName, type, asyncFn, fn) {
function resolveResult(defer, file, val) {
function resolveResult(defer, file, i, val) {
if (val != null) {
asyncFn(file, val).then(function (d) {
if (!fn(d, val)) {
file.$error = name;
(file.$errorMessages = (file.$errorMessages || {}))[name] = true;
file.$errorParam = val;
if (ignoredErrors.indexOf(name) === -1) {
file.$error = name;
(file.$errorMessages = (file.$errorMessages || {}))[name] = true;
file.$errorParam = val;
if (invalidFiles.indexOf(file) === -1) {
invalidFiles.push(file);
}
if (!runAllValidation) {
files.splice(i, 1);
}
} else {
files.splice(i, 1);
}
defer.reject();
} else {
defer.resolve();
}
}, function () {
if (attrGetter('ngfValidateForce', {$file: file})) {
file.$error = name;
(file.$errorMessages = (file.$errorMessages || {}))[name] = true;
file.$errorParam = val;
if (ignoredErrors.indexOf(name) === -1) {
file.$error = name;
(file.$errorMessages = (file.$errorMessages || {}))[name] = true;
file.$errorParam = val;
if (invalidFiles.indexOf(file) === -1) {
invalidFiles.push(file);
}
if (!runAllValidation) {
files.splice(i, 1);
}
} else {
files.splice(i, 1);
}
defer.reject();
} else {
defer.resolve();
Expand All @@ -1805,7 +1827,7 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct
var promises = [upload.emptyPromise()];
if (files) {
files = files.length === undefined ? [files] : files;
angular.forEach(files, function (file) {
angular.forEach(files, function (file, index) {
var defer = $q.defer();
promises.push(defer.promise);
if (type && (file.type == null || file.type.search(type) !== 0)) {
Expand All @@ -1814,20 +1836,20 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct
}
if (name === 'dimensions' && upload.attrGetter('ngfDimensions', attr) != null) {
upload.imageDimensions(file).then(function (d) {
resolveResult(defer, file,
resolveResult(defer, file, index,
attrGetter('ngfDimensions', {$file: file, $width: d.width, $height: d.height}));
}, function () {
defer.reject();
});
} else if (name === 'duration' && upload.attrGetter('ngfDuration', attr) != null) {
upload.mediaDuration(file).then(function (d) {
resolveResult(defer, file,
resolveResult(defer, file, index,
attrGetter('ngfDuration', {$file: file, $duration: d}));
}, function () {
defer.reject();
});
} else {
resolveResult(defer, file,
resolveResult(defer, file, index,
upload.getValidationAttr(attr, scope, name, validationName, file));
}
});
Expand Down Expand Up @@ -1904,9 +1926,25 @@ ngFileUpload.service('UploadValidate', ['UploadDataUrl', '$q', '$timeout', funct
return r === true || r === null || r === '';
})));

return $q.all(promises).then(function () {
deffer.resolve(ngModel, ngModel.$ngfValidations);
$q.all(promises).then(function () {

if (runAllValidation) {
for (var i = 0; i < files.length; i++) {
var file = files[i];
if (file.$error) {
files.splice(i--, 1);
}
}
}

runAllValidation = false;
validateSync('maxFiles', null, function (file, val, i) {
return prevLength + i < val;
});

deffer.resolve({'validFiles': files, 'invalidFiles': invalidFiles});
});
return deffer.promise;
};

upload.imageDimensions = function (file) {
Expand Down
Loading

0 comments on commit 003b1ef

Please sign in to comment.