24

I have a file upload control in my form.I am using Angular JS . When I put the required attribute to validate that the file is selected it is not working.

<input id="userUpload" name="userUpload" required type="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />

<button type="submit" class="btn btn-primary"><i class="icon-white icon-ok"></i>&nbsp;Ok</button>

Can you please suggest why the required is not working ?

thomaux
  • 19,133
  • 10
  • 76
  • 103
Moiz
  • 2,409
  • 5
  • 27
  • 50

2 Answers2

43

It's the ngModelController that does the validation in Angular based on attributes like require. However, currently there is no support for input type="file" with the ng-model service. To get it working you could create a directive like this:

app.directive('validFile',function(){
  return {
    require:'ngModel',
    link:function(scope,el,attrs,ngModel){
      //change event is fired when file is selected
      el.bind('change',function(){
        scope.$apply(function(){
          ngModel.$setViewValue(el.val());
          ngModel.$render();
        });
      });
    }
  }
});

Example markup:

  <div ng-form="myForm">
    <input id="userUpload" ng-model="filename" valid-file name="userUpload" required type="file" accept="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet" />
    <button ng-disabled="myForm.$invalid" type="submit" class="btn btn-primary"><i class="icon-white icon-ok"></i>&nbsp;Ok</button>
    <p>
      Input is valid: {{myForm.userUpload.$valid}}
      <br>Selected file: {{filename}}
    </p>
  </div>

Check out my working plnkr example.

joakimbl
  • 18,081
  • 5
  • 54
  • 53
  • I have already included SHIV for IE. I am going to put this code.will this work ? – Moiz Apr 25 '13 at 08:13
  • I don't even know what your code does - my sniplet should be IE8 compatible. Include it, test it and if it doesn't work in IE8 create a new question – joakimbl Apr 25 '13 at 08:17
  • You can test http://run.plnkr.co/CEMX0RY3MX1TbcSZ/ in IE8 (I just did and it worked fine) – joakimbl Apr 25 '13 at 08:19
  • 1
    Your example throws an exception in jQuery. – Jon Rimmer Jul 17 '13 at 13:58
  • @JonRimmer It's a little bug in the directive http://stackoverflow.com/questions/18383446/how-to-validate-form-with-inputtype-file-in-angularjs – DarkLeafyGreen Aug 22 '13 at 15:09
  • This wasn't resetting for me when I re-opened the form in a modal, so I had to add `ngModel.$setViewValue("");` as the first line of the `link` function and now it works sweet. Thanks! Though it would be nice for this to auto-majicially hook into `:input[type='file'][required]`! I could do this easily in jQuery, but Angular... research here I come! – Campbeln Aug 14 '14 at 07:15
  • Works perfectly. Thanks. I would suggest to name it 'passFile' since it actually passes the file path to the model (that then can validate it) – Jürgen Bayer Sep 10 '14 at 18:42
11

Extending @joakimbl code I will suggest the direct like this

.directive('validFile',function(){
    return {
        require:'ngModel',
        link:function(scope,el,attrs,ctrl){
            ctrl.$setValidity('validFile', el.val() != '');
            //change event is fired when file is selected
            el.bind('change',function(){
                ctrl.$setValidity('validFile', el.val() != '');
                scope.$apply(function(){
                    ctrl.$setViewValue(el.val());
                    ctrl.$render();
                });
            });
        }
    }
})

and in html you can use like this

<input type="file" name="myFile" ng-model="myFile" valid-file />
<label ng-show="myForm.myFile.$error.validFile">File is required</label>
FarazShuja
  • 2,287
  • 2
  • 23
  • 34
  • It's kind of odd, but using your code properly sets `myForm.myFile.$error.validFile` to true, but ng-show is not working. Using `myForm.myFile.$invalid` is working properly. I don't get why is it. My angular inspector shows validFile as true... – Luis Sieira Sep 11 '15 at 08:26
  • 1
    Okay, I got it... i changed validFile to valid-file, and i was looking for `myForm.myFile.$error.valid` minus `file` – Luis Sieira Sep 11 '15 at 08:29