简体   繁体   中英

How to validate form with input[type=file] in angularjs

HTML:

<form name="form">
    <input type="file" ng-model="document" valid-file required>
    <input type="submit" value="{{ !form.$valid && 'invalid' || 'valid' }}">
</form>

Custom directive to listen for input[type=file] changes:

myApp.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();
                 });
            });
        }
    };
});

When file is selected following error appears in console:

Error: InvalidStateError: DOM Exception 11 Error: An attempt was made to use an object that is not, or is no longer, usable.

Try with plunkr: http://plnkr.co/edit/C5j5e0JyMjt9vUopLDHc?p=preview

Without the directive the the state of the input file field wont be pushed to form.$valid. Any ideas why I get this error and how to fix this?

From the reference of NgModelController.$render()

Called when the view needs to be updated. It is expected that the user of the ng-model directive will implement this method.

You need to implement $render() to call it. You can do something like this

myApp.directive('validFile', function () {
    return {
        require: 'ngModel',
        link: function (scope, el, attrs, ngModel) {
            ngModel.$render = function () {
                ngModel.$setViewValue(el.val());
            };

            el.bind('change', function () {
                scope.$apply(function () {
                    ngModel.$render();
                });
            });
        }
    };
});

DEMO

After updating to AngularJS 1.2.x the snippet looks not working properly anymore and the file input doesn't sticks with the selected file value, making the form unusable. Changing the directive back to your original one, and removing the ngModel.$render() it looks working like a charm:

.directive('validFile', function () {
  return {
    restrict: 'A',
    require: '?ngModel',
    link: function (scope, el, attrs, ngModel) {
      el.bind('change', function () {
        scope.$apply(function () {
          ngModel.$setViewValue(el.val());
        });
      });
    }
  };

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM