Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Call a Directive Controller's method from Parent Controller in AngularJS

Tags:

angularjs

I am using AngularJS and I have a directive which has its own Controller. It inherits the scope of the Parent Controller.

As an example, consider the following:

function ParentCtrl() {
    $scope.aMethod = function() {
        // DO SOMETHING
    };
}

function ChildCtrl() {
    $scope.bMethod = function() {
        // DO SOMETHING ELSE
    }
}  

Now, $scope.aMethod of ParentCtrl() is triggered by a ng-click directive. What I want to do is call $scope.bMethod of ChildCtrl(). How can I do it?

EDIT: Some more information. The template associated with the ParentCtrl has a button and multiple directives. Each directive loads a form with different sets of inputs. When the button in the ParentCtrl Template is clicked, the directives are loaded one after another by means of ng-switch onand ng-switch-when.
When the user clicks the button, the ChildCtrl which belongs to the directives is meant to store the data in their respective forms.
Thus, when the button is clicked:
1. The ChildCtrl saves the model associated with the current directive that has been loaded.
2. The ParentCtrl loads the next directive in the series.
ng-click is bound to the button which is associated with ParentCtrl. But ChildCtrl also needs to do some action (save the form data) when that button is clicked. How does one accomplish that?

like image 458
callmekatootie Avatar asked Dec 11 '22 17:12

callmekatootie


2 Answers

Please have a look at the following.

I'm using the concept of $broadcast. I have tired to replicate the scenarios you have given like parent controller, child directive with its own controller etc:

var animateAppModule = angular.module('animateApp', [])
animateAppModule.controller('tst', function($scope) {
  $scope.test = function() {
    $scope.$broadcast('clickMessageFromParent', {
      data: "SOME msg to the child"
    })
  }
}).directive('myDirective', function() {
  return {
    controller: function($scope) {

    },
    link: function($scope, element) {
      $scope.$on('clickMessageFromParent', function(scopeDetails, msgFromParent) {
        //console.log(msgFromParent)
        element[0].innerHTML = msgFromParent.data;
      })
    }
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="tst">
  <input type="button" ng-click="test()" value="click" />
  <div my-directive="somvalue"></div>
</div>

JSFiddle

like image 174
Rajkamal Subramanian Avatar answered Feb 16 '23 00:02

Rajkamal Subramanian


This is similar to what rajkamal is saying, in that you'll need to use broadcast... however you'll want to dynamically change the broadcast to target whichever child you need to.

Here is a plunker showing an example

And here's the code:

app.controller('MainCtrl', function($scope) {

  // a method that broadcasts to a selected child.
  $scope.broadcastToSelectedChild = function (){
    $scope.$broadcast('call-' + $scope.broadcastTo);
  };
});

app.directive('testDir', function (){
  return {
    restrict: 'E',
    scope: {
      'name': '@'
    },
    template: '<div>{{name}} called: {{called}}</div>',
    link: function(scope, elem, attr) {

      scope.called = false;

      //a child function to call.
      scope.childFunction = function (){
        scope.called = true;
      };

      //set up the name to be used as the listened to event.
      var removeOn;
      scope.$watch('name', function(v) {
        if(removeOn) removeOn();
        removeOn = scope.$on('call-' + scope.name, function (){
            scope.childFunction();
          });
      });
    }
  };
});

and here it is in HTML:

  <div ng-controller="MainCtrl">
    <test-dir name="test1"></test-dir>
    <test-dir name="test2"></test-dir>
    <test-dir name="test3"></test-dir>
    <select ng-model="broadcastTo" ng-options="x as x for x in ['test1', 'test2', 'test3']"></select>
    <button ng-click="broadcastToSelectedChild()">test</button>
  </div>

What I did here is create a mechanism by which I can name my directives, and then broadcast to them by name. If the code isn't self explanatory, let me know. I hope this helps.

like image 23
Ben Lesh Avatar answered Feb 16 '23 00:02

Ben Lesh