Andres
Andres

Reputation: 4501

Angular.js call directive function in controller

I want to call a function defined in a directive, just the opposite of this stackoverflow question

I tried this but does not work.

app.directive('myDirective', function() {
    return {
        link: function(scope, element, attrs) {
            scope.someDirectiveFn = function(arg) {
                 return "in directive";
            };
        },
    }
});

function MyCtrl($scope) {
    alert($scope.someDirectiveFn());
}

Is that possible? how could I get it? is it a bad practice?

EDIT

I got this way:

.controller('MyCtrl', function($scope) {
    alert($scope.func());
})

.directive('myDirective', function() {
    return {
      controller: function($scope, $element){
        $scope.func = function() {
          return "text";
         };
      }
    }
});

Upvotes: 2

Views: 934

Answers (3)

halilb
halilb

Reputation: 4115

You can use event system to achieve that.

First, emit a custom event on your scope with your parameters. Second, listen to the scope in your directive with angular $on method.

app.controller('MyCtrl', function($scope) {
  $scope.invokeDirectiveMethod = function() {
    $scope.$emit('invokeMyDirectiveMethod', 'myParameter');
  };
})

.directive('myDirective', function() {
  return {
    link: function(scope, element, attrs) {
      var someDirectiveFn = function(event, arg) {
        alert(arg + " in directive");
      };

      scope.$on('invokeMyDirectiveMethod', someDirectiveFn);
    },
  }
});

Here is a working plunker.

UPDATE

Based on your update, event communication does not fit your problem.

How about passing an object to directive using two way binding and defining someDirectiveFn in that object? This way you can pass arguments and return values from it.

app.controller('MyCtrl', function($scope) {
  $scope.shareObject = {};

  $scope.invokeDirectiveMethod = function() {
    if (angular.isFunction($scope.shareObject.someDirectiveFn)) {
      $scope.message = $scope.shareObject.someDirectiveFn('from controller'); 
    }
  };
})

.directive('myDirective', function() {
  return {
    scope: {
      'shareObject': '='
    },
    link: function(scope, element, attrs) {
      scope.shareObject.someDirectiveFn = function(arg) {
        return arg + ' from parameter';
      };
    },
  }
});

Updated plunker.

Upvotes: 3

Jonas
Jonas

Reputation: 1345

You didnt post your html code, so I assume that your custom directive is used IN MyCtrl. This does not work because of when the functions are executed.

Controller functions are always executed before link functions.

Here is a cool article about the differences.

So if you want your controller to be able to invoke a function in the directive you can broadcast events (like in halilb's answer) or make the directive to listen to specific scope values, like this:

app.directive('myDirective', function() {
    return {
        link: function(scope, element, attrs) {
            scope.$watch("message", function() { console.log(message); });
        },
    }
});

function MyCtrl($scope) {
    $scope.message = "Hello Directive";
}

Upvotes: 1

ssayyed
ssayyed

Reputation: 796

I'm guessing you want to have a function that is shared between a directive and a controller lets say?

if thats the case how about creating a service and injecting the service into both directive and ctrl. This way you would only have to create it once.

  app.service('sharedFucntionService', function() {
     return {
        someFn : function (arg) {
             alert(arg + " in directive")  
        }
    }
 });

Injecting the service into a directive

 app.directive('myDirective',function( sharedFucntionService){
  return {
        link: function (scope, element, attrs) {
            // do something with sharedFucntionService
        }
    }

});

Inject the service into the controller as well function MyCtrl($scope, sharedFucntionService){ ...... }

Upvotes: 0

Related Questions