angularJS: How to call child scope function in parent scope

AngularjsAngularjs Scope

Angularjs Problem Overview


How can call a method defined in child scope from its parent scope?

function ParentCntl() {
    // I want to call the $scope.get here
}

function ChildCntl($scope) {
    $scope.get = function() {
        return "LOL";    
    }
}

http://jsfiddle.net/wUPdW/

Angularjs Solutions


Solution 1 - Angularjs

You can use $broadcast from the parent to a child:

function ParentCntl($scope) {

    $scope.msg = "";
    $scope.get = function(){
        $scope.$broadcast ('someEvent');
        return  $scope.msg;        
    }
}

function ChildCntl($scope) {               
    $scope.$on('someEvent', function(e) {  
        $scope.$parent.msg = $scope.get();            
    });
    
    $scope.get = function(){
        return "LOL";    
    }
}

Working fiddle: http://jsfiddle.net/wUPdW/2/

UPDATE: There is another version, less coupled and more testable:

function ParentCntl($scope) {
    $scope.msg = "";
    $scope.get = function(){
        $scope.$broadcast ('someEvent');
        return  $scope.msg;        
    }
    
    $scope.$on('pingBack', function(e,data) {  
        $scope.msg = data;        
    });
}

function ChildCntl($scope) {               
    $scope.$on('someEvent', function(e) {  
        $scope.$emit("pingBack", $scope.get());        
    });
    
    $scope.get = function(){
        return "LOL";    
    }
}

Fiddle: http://jsfiddle.net/uypo360u/

Solution 2 - Angularjs

Let me suggest another solution:

var app = angular.module("myNoteApp", []);


app.controller("ParentCntl", function($scope) {
    $scope.obj = {};
});

app.controller("ChildCntl", function($scope) {
    $scope.obj.get = function() {
            return "LOL";    
    };
});

Less code and using prototypical inheritance.

Plunk

Solution 3 - Angularjs

Register the child's function on the parent when the child is initialising. I used "as" notation for clarity in the template.

TEMPLATE

<div ng-controller="ParentCntl as p">
  <div ng-controller="ChildCntl as c" ng-init="p.init(c.get)"></div>
</div>

CONTROLLERS

...
function ParentCntl() {
  var p = this;
  p.init = function(fnToRegister) {
    p.childGet = fnToRegister;
  };
 // call p.childGet when you want
}

function ChildCntl() {
  var c = this;
  c.get = function() {
    return "LOL";    
  };
}

"But", you say, "ng-init isn't supposed to be used this way!". Well, yes, but

  1. that documentation doesn't explain why not, and
  2. I don't believe the documentation authors considered ALL possible use cases for it.

I say this is a good use for it. If you want to downvote me, please comment with reasons! :)

I like this approach because it keeps the components more modular. The only bindings are in the template, and means that

  • the child Controller doesn't have to know anything about which object to add its function to (as in @canttouchit's answer)
  • the parent control can be used with any other child control which has a get function
  • doesn't require broadcasting, which will get very ugly in a big app unless you tightly control the event namespace

This approach more closely approaches Tero's idea of modularising with directives (note that in his modularised example, contestants is passed from parent to "child" directive IN THE TEMPLATE).

Indeed another solution might be to consider implementing the ChildCntl as a directive and use the & binding to register the init method.

Solution 4 - Angularjs

You can make child object.

var app = angular.module("myApp", []);


app.controller("ParentCntl", function($scope) {
    $scope.child= {};
    $scope.get = function(){
      return $scope.child.get(); // you can call it. it will return 'LOL'
    }
   // or  you can call it directly like $scope.child.get() once it loaded.
});

app.controller("ChildCntl", function($scope) {
    $scope.obj.get = function() {
            return "LOL";    
    };
});

Here child is proving destination of get method.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
Question9blueView Question on Stackoverflow
Solution 1 - AngularjsIvan ChernykhView Answer on Stackoverflow
Solution 2 - AngularjsCanttouchitView Answer on Stackoverflow
Solution 3 - AngularjsposhestView Answer on Stackoverflow
Solution 4 - AngularjsRamu AgrawalView Answer on Stackoverflow