Как проверить форму с помощью ввода [type = file] в angularjs

HTML:

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

Пользовательская директива для прослушивания ввода [type = file] изменяется:

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

Когда файл выбран, в консоли появляется следующая ошибка:

Ошибка: InvalidStateError: ошибка DOM 11 Ошибка: попытка была сделана использовать объект, который не является или больше не может использоваться.

Попробуйте с помощью plunkr: http://plnkr.co/edit/C5j5e0JyMjt9vUopLDHc?p=preview

Без директивы состояние поля входного файла не будет вытолкнено. $valid. Любые идеи, почему я получаю эту ошибку и как это исправить?

Ответ 1

Из ссылки NgModelController. $render()

Вызывается, когда представление необходимо обновить. Ожидается, что пользователь директивы ng-model будет реализовывать этот метод.

Вам нужно реализовать $render(), чтобы вызвать его. Вы можете сделать что-то вроде этого

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

Ответ 2

После обновления до AngularJS 1.2.x сниппет выглядит некорректно, и входной файл не совпадает с выбранным значением файла, делая форму непригодной. Изменив директиву на исходную, и удалив ngModel.$render(), он выглядит как шарм:

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