Zach
Zach

Reputation: 3207

Why is my directive updating as a result of changes in another instance of the same directive?

I created a simple directive wrapper around the HTML file input to make angular binding work. Here's my directive:

angular.module('myApp').directive('inputFile', InputFileDirective);

function InputFileDirective() {
  var bindings = {
    selectLabel: '@',
  };
  return {
    restrict: 'E',
    require: ['inputFile', 'ngModel'],
    scope: true,
    controllerAs: 'inputFileCtrl',
    bindToController: bindings,
    controller: function () {
    },
    template: `<input class="ng-hide" id="input-file-id" type="file" />
<label for="input-file-id" class="md-button md-raised md-primary">{{ inputFileCtrl.getButtonLabel() }}</label>`,
    link: link
  };

  function link(scope, element, attrs, controllers) {
    if (angular.isDefined(attrs.multiple)) {
      element.find('input').attr('multiple', 'multiple');
    }
    var inputFileCtrl = controllers[0];
    var ngModelCtrl = controllers[1];

    inputFileCtrl.getButtonLabel = function () {
      if (ngModelCtrl.$viewValue == undefined || ngModelCtrl.$viewValue.length == 0) {
        return inputFileCtrl.selectLabel;
      }
      else {
        return ngModelCtrl.$viewValue.length + (ngModelCtrl.$viewValue.length == 1 ? " file" : " files") + " selected";
      }
    };

    element.on('change', function (evt) {
      ngModelCtrl.$setViewValue(element.find('input')[0].files);
      ngModelCtrl.$render();
    });
  }
};

And here's the HTML

<body ng-app="myApp" ng-controller="MyController as ctrl">
  <form name="ctrl.myForm">
    <input-file select-label="Select Attachment" ng-model="ctrl.attachment1"></input-file>

    <input-file select-label="Select Attachment" ng-model="ctrl.attachment2"></input-file>
  </form>
</body>

It's pretty simple and it works - if only one is on the page. As soon as I add a second one, I notice that only the first one ever updates. If I select a file with the second one, the label updates on the first one. My suspicions are that the require ['inputFile'] is pulling in the controller for the first directive instance into the link function or something (which shouldn't happen). Even now as I type this, that doesn't really make sense to me. So what's going on here and how do I fix it?

Here's a codepen for you guys to play with and try to figure it out: http://codepen.io/astynax777/pen/PzzBRv

Upvotes: 1

Views: 52

Answers (1)

Manatax
Manatax

Reputation: 4223

Your problem is not with your angular... is with you html. You are assigning the same id twice. Change your template to this:

template: `<label class="md-button md-raised md-primary">{{ inputFileCtrl.getButtonLabel() }}<input class="ng-hide" type="file" /></label>`

Upvotes: 1

Related Questions