0

I want to invoke a custom directive inside another custom directive's template. Please find below code snippets -

Scenario 1 (Not working)

angular.module('myApp')
.directive('customOnChange', function () {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      var onChangeFunc = scope.$eval(attrs.customOnChange);
      element.bind('change', function (event) {
        var files = event.target.files;
        onChangeFunc(files);
      });
      element.bind('click', function () {
        element.val('');
      });
    }
  };
})
.directive('writePost', function () {
  return {
    restrict: 'E',
    link: function (scope) {
      scope.changeUserProfileImage = function (files) {
        console.log(files); // I should receive uploaded files here.
      };
    },
    templateUrl: function () {
      return 'writePost.html';
    }
  };
});

index.html

<write-post></write-post>

writePost.html

<input type="file" ng-model="file" name="file"
       id="photo-upload1" custom-on-change="changeUserProfileImage"
       value="Change Image"
       title="Change Image"/>

The error I am receiving when I upload a file -

Uncaught TypeError: onChangeFunc is not a function

Scenario 2 (Working)

Although independently I am able to call customOnChange directive from index.html. Working code snippet -

index.html

<input type="file" ng-model="file" name="file"
       id="photo-upload1" custom-on-change="changeUserProfileImage"
       value="Change Image"
       title="Change Image"/>

myCtrl.js

angular.module('myApp')
.controller('myCtrl', ['$scope', function ($scope) {
  $scope.changeUserProfileImage = function (files) {
     console.log(files); // I am receiving uploaded files here.
  };
}]);

Can someone help me identifying, where I am going wrong in first scenario ?

georgeawg
  • 48,608
  • 13
  • 72
  • 95
  • Consider refactoring by replacing the `customOnChange` directive with the [`select-ng-files` directive](https://stackoverflow.com/a/43074638/5535245). The latter integrates with the `ng-model` directive and the `ng-form` directive providing better integration with the AngularJS framework. – georgeawg Jul 10 '20 at 10:53

1 Answers1

1

link in directive definition defaults to postLink - it executes after template with its directives is parsed. (read more here https://docs.angularjs.org/api/ng/service/$compile#pre-linking-function)

As a solution you can move $eval inside callback:

  element.bind('change', function (event) {
    var onChangeFunc = scope.$eval(attrs.customOnChange);
    var files = event.target.files;
    onChangeFunc(files);
  });

Correct way:

If you want run function - let it be function in html:

custom-on-change="changeUserProfileImage(files)"

Now run it as function:

  element.bind('change', function (event) {
    var files = event.target.files;
    scope.$eval(attrs.customOnChange, {files: event.target.files});
  });
Petr Averyanov
  • 9,327
  • 3
  • 20
  • 38