15

I am using angular 1.5 component and need to call function in parent controller from when $emit in child component. How we can do this?

Example:

(function (angular) {
    'use strict';

    controllerName.$inject = [];

    function controllerName() {
       var _this = this;
       function toBeCalledOnEmit() {//some code}
       var vm = {
          toBeCalledOnEmit: toBeCalledOnEmit
       }
       angular.extend(_this, vm);
    }

    angular.module('moduleName', [
    ]).component('parentComponenet', {
        templateUrl: 'templateUrl',
        controller: 'controllerName'
    }).controller('controllerName', controllerName);

})(angular);

child component:

(function (angular) {
    'use strict';

    childController.$inject = [];

    function childController() {
       //needs $emit here
    }

    angular.module('childModuleName', [
    ]).component('childComponent', {
        templateUrl: 'templateUrl',
        controller: 'childController'
    }).controller('childController', childController);

})(angular);
Amir Suhail
  • 1,284
  • 3
  • 12
  • 31
  • 7
    I have used $emit, $broadcast and $on before 1.5, but in 1.5 component we are not using $scope or $rootscope. How to achieve this without $scope? In docs $emit is using with $scope. – Amir Suhail May 18 '16 at 06:41

3 Answers3

14

I prefer working with a separate event service that exposes subscribe and notify functions. But if you prefer to emit from the child component then it would look like this:

Child Component

    (function (angular) {
    'use strict';

      function childController($scope) {
       $scope.$emit("someEvent", args); 
      }

      angular.module('childModuleName', [
      ]).component('childComponent', {
        templateUrl: 'templateUrl',
        controller: ['$scope', childController]
      });

    })(angular);

Parent Component

    (function (angular) {
    'use strict';


      function controllerName($scope) {
         var _this = this;

         function toBeCalledOnEmit(event, args) {
            //some code
         }
         $scope.on('someEvent', toBeCalledOnEmit);

         var vm = {
            toBeCalledOnEmit: toBeCalledOnEmit
         }
         angular.extend(_this, vm);
      }

      angular.module('moduleName', [
      ]).component('parentComponent', {
          templateUrl: 'templateUrl',
          controller: ['$scope', controllerName]
      });

    })(angular);
Backer
  • 1,094
  • 1
  • 20
  • 33
AranS
  • 1,871
  • 10
  • 22
  • 1
    using $rootScope like @Praveen Poonia did is a good idea when we want a single place of notifying and subscribing (although, as far as I know, $rootScope and $scope will be deprecated in Angular 2). – AranS May 18 '16 at 06:59
  • I wouldn't advise using `$rootScope`. After doing some reading it would seem that's potential for a memory leak. See [here](http://stackoverflow.com/questions/24830679/why-do-we-use-rootscope-broadcast-in-angularjs) for further details. – wootencl Sep 12 '16 at 19:37
  • `this` is undefined.. see here: https://stackoverflow.com/q/48691233/766570 – abbood Feb 08 '18 at 17:26
  • What does the `angular.extend()` part do? Is it just binding the event payload so it becomes a property on the parent component...? – Rich May 10 '21 at 22:47
3

Code is attached below:

  1. Child Component:

    (function (angular) {
        'use strict';
    
    childController.$inject = ['$scope'];
    
    function childController($scope) {
    
       //needs $emit here
    $scope.$emit("topic-123", 'any message'); 
    }
    
    angular.module('childModuleName', [
    ]).component('childComponent', {
        templateUrl: 'templateUrl',
        controller: 'childController'
    }).controller('childController', childController);
    

    })(angular);

  2. Parent Component:

    (function (angular) {
    'use strict';
    
    controllerName.$inject = ['$scope'];
    
    function controllerName($scope) {
       var _this = this;
       function toBeCalledOnEmit() {//some code}
       var vm = {
          toBeCalledOnEmit: toBeCalledOnEmit
       }
    
       $scope.$on('topic-123', function(event, msg) {
      // @TODO  
      toBeCalledOnEmit();
       });
    
       angular.extend(_this, vm);
    }
    
    angular.module('moduleName', [
    ]).component('parentComponenet', {
        templateUrl: 'templateUrl',
        controller: 'controllerName'
    }).controller('controllerName', controllerName);
    

    })(angular);

Suneet Bansal
  • 2,664
  • 1
  • 14
  • 18
2

You can do it like this using $rootScope. It works fine in my case -

child component:

(function (angular) {
 'use strict';

 childController.$inject = ['$rootScope'];

 function childController($rootScope) {
   $rootScope.$emit('myEvent',$scope.data)
 }
})(angular);

Parent Component:

(function (angular) {
 'use strict';

 controllerName.$inject = ['$rootScope'];

 function controllerName($rootScope) {
   var _this = this;
   function toBeCalledOnEmit() {//some code}
   var vm = {
      toBeCalledOnEmit: toBeCalledOnEmit
   }
   $rootScope.$on('myEvent', function(event, msg) {
     toBeCalledOnEmit();
   });
   angular.extend(_this, vm);
 }
})(angular);
dmansfield
  • 1,108
  • 10
  • 22
Praveen Poonia
  • 745
  • 10
  • 18