AngularJS: How do I call a function defined in a d

2019-06-07 22:39发布

I need to call a function which belongs to the $scope of a ng-directive used in my Angular application.

Let's say the directive is defined like this:

.directive('my-directive', ['$document', '$timeout', function ($document, $timeout) {
    return {
        restrict: 'E',
        replace: true,
        scope: {
            // ....
        },
        controller: ['$scope', function ($scope) {

            $scope.myFunction= function (mouseEnter) {
                // ...
            };
        }
    };
}]);

I need to call myFunction from my controller (let's call it my-controller) which is the controller of the view where my directive is placed.

Is it possible to do it? (eventually modifying the directive)

EDIT : The already answered question provided (proposed for edit) is similar to mine by it's not clear to me or it doesn't apparently solve the specific problem I proposed.

EDIT 2: starting from Dan M. answer (without taking mouseenter/mouseleave in consideration. just trying to make the two controllers communicate with each other), I broadcasted my event to my directive's controller through $rootScope (as there is there is no parent-child relation between the two controllers) by:

console.log("let's broadcast the event.."); // this is printed
$rootScope.$broadcast('callDirectiveControllersFunction'); // I even tried with $scope in place of $rootScope and $emit in place of $broadcast

and by receving it (within the directive's controller) by:

var myFunction = function(){
   // ...
}

$scope.$on('callDirectiveControllersFunction', function (){
   console.log("event received"); // this is not printed
   callMyFunction(); 
});
// I even tried using $rootScope in place of $scope

However in no case (see comments in code) the event is received

1条回答
Emotional °昔
2楼-- · 2019-06-07 23:08

You can call a controller function inside the link block. You can also $emit an event in the directive and listen to the it in the controller (maybe there is a use case for that).

It seems that you want to call it on mouseenter. You can do that by binding to the mouseenter event in the directive link. The catch is you need to $apply the changes. Take a look at the following piece of code, which contains all 3 examples: http://jsbin.com/cuvugu/8/. (also pasted below)

Tip: You might want to pay attention to how you name your directives. To use a directive as my-directive you need to name it as myDirective.

var app = angular.module('App', []);

app.directive('myDirective', function () {
  function directiveLink(scope){
    scope.$emit('customEvent');
  }

  return {
    restrict: 'EA',
    scope: {},
    link: directiveLink,
    controller: function ($scope) {
      $scope.bar = 'bar';
      $scope.myFunction = function () {
        $scope.bar = 'foobar1';
      };

      $scope.$on('customEvent', function (){
        $scope.myFunction();
      });
    },
    template: "Foo {{bar}}"
  };
});

app.directive('anotherDirective', function () {
  function directiveLink(scope){
    scope.myFunction();
  }

  return {
    restrict: 'EA',
    scope: {},
    link: directiveLink,
    controller: function ($scope) {
      $scope.bar = 'bar';
      $scope.myFunction = function () {
        $scope.bar = 'foobar2';
      };
    },
    template: "Foo {{bar}}"
  };
});

app.directive('mouseDirective', function () {
  function directiveLink(scope, element){
    element.bind('mouseenter', function(){
      scope.$apply(function(){
        scope.myFunction();
      });
    });

    element.bind('mouseleave', function(){
      scope.$apply(function(){
        scope.myOtherFunction();
      });
    });
  }

  return {
    restrict: 'EA',
    link: directiveLink,
    controller: function ($scope) {
      $scope.bar = 'no';
      $scope.myFunction = function () {
        $scope.bar = 'yes';
      };

      $scope.myOtherFunction = function () {
        $scope.bar = 'no';
      };
    },
    template: "Mouse Enter: {{bar}}"
  };
});

I also included an example with a distinct controller in the JS Bin link. That doesn't really change anything, but it seems to be an important part of your question. Here's the code block:

var app = angular.module('App', []);

app.controller('myController', function($scope){
  $scope.bar = 'foo';

  $scope.myFunction = function(){
    $scope.bar = 'foobar3';
  };
});

app.directive('lastDirective', function () {
  function directiveLink(scope){
    scope.myFunction();
  }

  return {
    restrict: 'EA',
    scope: {},
    link: directiveLink,
    controller: 'myController',
    template: "Foo {{bar}}"
  };
});
查看更多
登录 后发表回答