Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 1.5, Calling a function in a component from Parent controller

Tags:

angularjs

Angular 1.5 components easily allow creating a call back to the parent from the component. Is there a way i can call a function in a component from a function in parent's controller ?

Lets say my component is called task-runner and below is the HTML for it in the parent container.

<task-runner taskcategogyid=5></task-runner>   <button type="button" ng-click="doSomethingInParent()">ParentToChildButton</button> 

The plunkr is here. I want that when ParentToChildButton is clicked, the function doSomethingInParent() calls the remotefunc in component.

like image 463
TkNeo Avatar asked May 13 '16 16:05

TkNeo


2 Answers

A few different ways:

  1. Pass an object as an attribute with two-way binding (scope:{myattr:'='}) to the task-item-header directive which the directive could then add a function to for the parent controller to call.
  2. Set an attribute that has either one-way binding (scope:{myattr:'@'}) on it and then attrs.$observe changes to it to trigger the action, or two-way binding (scope:{myattr:'='}) and then $scope.$watch changes to it to trigger the action.
  3. Have the directive raise an event (scope:{raiseLoaded:'&onLoaded'}) that passes an object that represents a remote control object with a method on it that triggers the action you want. To raise the event, you'd call something like raiseLoaded({remoteControl: remoteControlObj}) within the directive, and then to listen to the event, you'd use <task-item-header on-loaded="setRemote(remoteControl)"> assuming you have a setRemote() method on your parent controller.

Update I just realized your question was for a newer version of AngularJS, so I'm not sure if my answer still applies. I'll leave it here for now, but if you find it is not helpful I can delete it.

like image 151
adam0101 Avatar answered Oct 12 '22 09:10

adam0101


I needed something like this previously so I thought I would share how I solved this problem.

Similar to the OP, I needed to freely trigger methods in child components from a parent component. I wanted to be able to trigger this method in the parent freely/separately without the use of the $onChanges lifecycle hook.

Instead I created a notification-registration mechanism to allow a child component to 'register' a method with the parent when it is loaded. This method can then be freely triggered by the parent outside of the $onChanges cycle.

I created a codepen to demonstrate this. It can be easily extended to handle different types of notifications from the parent that aren't related to the data changes.

Index.html

<div ng-app="tester">   <parent></parent> </div> 

Script.js

angular.module('tester', []);  angular.module('tester').component('parent', {   controller: parentController,   template: `     <div class="tester-style">       <button ng-click="$ctrl.notifyChild()">Notify child</button>       <child parent-to-child-notification-registration="$ctrl.childComponentNotificationRegistration(handler)">     </div>   ` });  function parentController() {   let childComponentEventHandler = null;    this.$onInit = function() {     this.value = 0;   };    this.childComponentNotificationRegistration = function(handler) {     childComponentEventHandler = handler;     console.log('Child component registered.');   };    this.notifyChild = function() {     if (childComponentEventHandler) {       childComponentEventHandler(this.value++);     }   }; }  angular.module('tester').component('child', {   bindings: {     parentToChildNotificationRegistration: '&',   },   controller: childController,   template: `     <div class="tester-style">       <h4>Child Component</h4>     </div>   ` });  function childController() {   this.$onInit = function() {     this.parentToChildNotificationRegistration({       handler: this.processParentNotification     });   };    this.processParentNotification= function(parentValue) {     console.log('Parent triggered child notification handler!!!');     console.log('Value passed to handler:', parentValue);   }; }; 

}

Also for something similar to @adam0101's #3 answer see codepen.

like image 39
rdrw Avatar answered Oct 12 '22 11:10

rdrw