From 53d1b4900d8151c3dd30af038c90193bdb4adf68 Mon Sep 17 00:00:00 2001 From: Nick Litwin Date: Tue, 5 Jan 2016 14:21:24 -0800 Subject: [PATCH] Add validation and error handling for file inputs --- .../tc-file-input/tc-file-input.directive.js | 37 ++++++++++++++---- .../tc-file-input/tc-file-input.jade | 6 +-- app/submissions/submit-file/submit-file.jade | 39 +++++++++++++++---- 3 files changed, 63 insertions(+), 19 deletions(-) diff --git a/app/directives/tc-file-input/tc-file-input.directive.js b/app/directives/tc-file-input/tc-file-input.directive.js index e6e2ceefa..278c9ad1a 100644 --- a/app/directives/tc-file-input/tc-file-input.directive.js +++ b/app/directives/tc-file-input/tc-file-input.directive.js @@ -6,20 +6,25 @@ function tcFileInput() { return { restrict: 'E', - require: '^form', + require: ['^form', '^ngModel'], templateUrl: 'directives/tc-file-input/tc-file-input.html', scope: { labelText: '@', fieldId: '@', placeholder: '@', fileType: '@', + showFileType: '=', mandatory: '=', buttonText: '@', setFileReference: '&', - fileValue: '=ngModel' + ngModel: '=' }, - link: function(scope, element, attrs, formController) { + link: function(scope, element, attrs, controllers) { + var formController = controllers[0]; + var ngModel = controllers[1]; + scope.selectFile = selectFile; + var fileTypes = scope.fileType.split(','); // fieldId is not set on element at this point, so grabbing with class .none // which exists on the element right away @@ -29,12 +34,28 @@ fileInput.bind('change', function() { var file = fileInput[0].files[0]; - // Pass file object up through callback into controller - scope.setFileReference({file: file, fieldId: scope.fieldId}); + var selectedFileType = file.type.slice(file.type.lastIndexOf('/') + 1); + var isAllowedFileFormat = _.some(fileTypes, _.matches(selectedFileType)); + + scope.$apply(function(){ + if (!isAllowedFileFormat) { + fileNameInput[0].value = file.name; + + // Manually setting is required since Angular doesn't support file inputs + formController[attrs.fieldId].$setTouched(); + formController[attrs.fieldId].$setValidity('required', false); + + } else { + // Pass file object up through callback into controller + scope.setFileReference({file: file, fieldId: scope.fieldId}); + + // Set the file name as the value of the disabled input + fileNameInput[0].value = file.name; - // Set the file name as the value of the disabled input - fileNameInput[0].value = file.name; - formController[attrs.fieldId].$setValidity('required', true); + // Manually set validity of specific input field + formController[attrs.fieldId].$setValidity('required', true); + } + }); }); function selectFile() { diff --git a/app/directives/tc-file-input/tc-file-input.jade b/app/directives/tc-file-input/tc-file-input.jade index 62128fd84..c1b097480 100644 --- a/app/directives/tc-file-input/tc-file-input.jade +++ b/app/directives/tc-file-input/tc-file-input.jade @@ -1,12 +1,12 @@ .tc-file-field__label label.tc-label {{labelText}} - span.lowercase(ng-if="fileType") {{fileType | addBeginningSpace}} + span.lowercase(ng-if="showFileType") {{ ' *(.' + fileType + ')'}} span.tc-label__mandatory.lowercase(ng-if="mandatory") #[span *]mandatory .tc-file-field__inputs - input.tc-file-field__input(type="text", placeholder="{{placeholder}}") + input.tc-file-field__input(type="text", placeholder="{{placeholder}}", disabled) button.tc-btn(ng-click="selectFile()") {{buttonText}} - input.none(name="{{fieldId}}", type="file", id="{{fieldId}}", required, ng-model="fileValue") + input.none(name="{{fieldId}}", type="file", required, ng-model="ngModel") diff --git a/app/submissions/submit-file/submit-file.jade b/app/submissions/submit-file/submit-file.jade index 183f252ee..0ba83fa04 100644 --- a/app/submissions/submit-file/submit-file.jade +++ b/app/submissions/submit-file/submit-file.jade @@ -29,35 +29,56 @@ label-text="Submission", field-id="SUBMISSION_ZIP", button-text="Add File", - file-type="(*.zip)", + file-type="zip", + show-file-type="true", placeholder="Attach all visible files as a single .zip file", mandatory="true", set-file-reference="vm.setFileReference(file, fieldId)", - file-value="vm.submissionForm.submissionZip" + ng-model="vm.submissionForm.submissionZip" ) + .tc-error-messages(ng-show="submissionForm['SUBMISSION_ZIP'].$touched && submissionForm['SUBMISSION_ZIP'].$invalid") + p(ng-show="submissionForm['SUBMISSION_ZIP'].$error.required") This is not the correct file format. Please select a .zip file. + tc-file-input.tc-file-field( label-text="Source", field-id="SOURCE_ZIP", button-text="Add File", - file-type="(*.zip)", + file-type="zip", + show-file-type="true", placeholder="Attach all source files as a single .zip file", mandatory="true", set-file-reference="vm.setFileReference(file, fieldId)", - file-value="vm.submissionForm.sourceZip" + ng-model="vm.submissionForm.sourceZip" ) + .tc-error-messages(ng-show="submissionForm['SOURCE_ZIP'].$touched && submissionForm['SOURCE_ZIP'].$invalid") + p(ng-show="submissionForm['SOURCE_ZIP'].$error.required") This is not the correct file format. Please select a .zip file. + tc-file-input.tc-file-field( label-text="Preview Image", field-id="DESIGN_COVER", button-text="Add File", + file-type="jpg,jpeg,png" placeholder="Image file as .jpg or .png", mandatory="true", set-file-reference="vm.setFileReference(file, fieldId)", - file-value="vm.submissionForm.designCover" + ng-model="vm.submissionForm.designCover" + ) + + .tc-error-messages(ng-show="submissionForm['DESIGN_COVER'].$touched && submissionForm['DESIGN_COVER'].$invalid") + p(ng-show="submissionForm['DESIGN_COVER'].$error.required") This is not the correct file format. Please select a .jpg or .png file. + + tc-input.fieldset__input.submitterRank( + label-text="Rank #", + input-name="Submission_Rank", + input-value="vm.submissionForm.submitterRank", + input-pattern="vm.rankRegEx", + update-value-on-blur="vm.setRankTo1(inputValue)" ) - tc-input.fieldset__input.submitterRank(label-text="Rank #", input-value="vm.submissionForm.submitterRank") + .tc-error-messages(ng-show="submissionForm.Submission_Rank.$dirty && submissionForm.Submission_Rank.$invalid") + p(ng-show="submissionForm.Submission_Rank.$error.pattern") Please enter a positive integer. .form-block.flex.wrap .form-block__instructions @@ -104,13 +125,15 @@ tc-input.fieldset__input( label-text="Font Name", placeholder="Select font source to edit field" - input-value="font.name" + input-value="font.name", + input-name="fontName{{$index}}" ) tc-input.fieldset__input( label-text="Font URL", placeholder="Select font source to edit field", - input-value="font.sourceUrl" + input-value="font.sourceUrl", + input-name="fontUrl{{$index}}" ) button.fieldset__button.tc-btn.tc-btn-s(type="button", ng-click="vm.createAnotherFontFieldset()") + Add Font