1

I have a directive like below. It's supposed to load a file from an <input type=file> and set it to an ng-model provided. It's also got some custom validation only incidental to my question. It's also on plunkr.

What's wrong is that the ngModel never gets set at all. It's always undefined. Why?

app.directive('fileInput', function () {
  var link = function (scope, element, attrs, ngModel) {
    var VALIDTYPES = ['text/csv', 'text/directory', 'text/vcard'];

    var updateModel = function () {
      var file = element[0].files[0];
      if (file) {
        scope.$apply(function () {
          if (VALIDTYPES.indexOf(file.type) >= 0) {
            ngModel.$setValidity("mimetype", true);
            ngModel.$setViewValue(file);
          } else {
            ngModel.$setValidity("mimetype", false);
            alert("Sorry, can only accept VCF and CSV files.");
          }
        })
      }
    };

    element.bind('change', updateModel);
  };

  return {
    restrict: 'A',
    require: 'ngModel',
    template: "<input type='file'>",
    replace: true,
    link: link,
    scope: {},
  }
});
cellofellow
  • 437
  • 5
  • 14

1 Answers1

0

This is fixed as of 1.2.0 due to this change:

Fixes issue with isolate scope leaking all over the place into other directives on the same element.

Isolate scope is now available only to the isolate directive that requested it and its template.

Before 1.2.0 if any directive on an element requested an isolate scope then all the directives on that element shared that scope.

In your case this caused the input directive to use the isolate scope you were requesting for your directive instead of the parent scope that the html <p>Filename is: {{ file.name }}</p> is on. Thus file was undefined because file was on a child scope

You can see that in action, pre 1.2.0, by copying the $viewValue up to the parent scope using this one line below your $setViewValue:

ngModel.$setViewValue(file);  
scope.$parent.file = ngModel.$viewValue;

You'll see in this updated plunker that fixes this problem in pre-1.2.0 code.

The best solution though is to move to 1.2.0. With 1.2.0 your isolate scope will only affect your directive and not the 'input' directive so everything works as expected in this plunker

KayakDave
  • 24,636
  • 3
  • 65
  • 68