Sharing data between Controller

Angularjs doesn’t allow the controller to define in another controller. “How do we achieved nesting controller and shared data between the nested controllers in AngularJS?”

At the time of implementation, even we made implementation of each controller separately and no relation between each controller. When we are binding this controller into the view, we define one controller within another only in view it becomes the as nested controller and has a relationship of parent and child.

  <div ng-controller="myCtrl1 as c1" >
    Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
    <div ng-controller="myCtrl2" >
      Controller 2 Message Date : <input type="text" ng-model="c1.msg"/>
    </div>
  </div>

 

We can easily access data model the of a parent in child controller and updating data model of parent will reflect in its child controller.

Problem: We will have a problem when updating data from child to parent. When specific data model is updated in the child, the data model will not be updated in parents. If a model object doesn’t have any kind of prototype reference then it will try to update data at scope level and even the data is defined at the parent or root scope. We need to define prototype for data model in controller and prototype is kind of reference. How to define prototype when it comes to scope object. We have a different approach to this problems.

1. Controller Aliasing
We can give an alias name to controller binding. We can give an alias name to myCtrl 1 as c1. As now c1 is acting as kind of prototype. When we are updating the data model object of a parent in child controller and the update will reflect in the parent. In this case, we are not creating in the model object while editing parent model in child and we are editing only parent model through aliasing. If we are not using aliasing method then editing msg in controller two will create it own msg data model at its own scope object. 

<html ng-app="myApp">
<html>
<head>
  <script src="js/angular.min.js"></script>
</head>
<body>
  <div ng-controller="myCtrl1 as c1" >
    Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
    <div ng-controller="myCtrl2" >
      Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
      <div ng-controller="myCtrl3" >
        Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
      </div>
    </div>
  </div>

<script>
  var app = angular.module("myApp", [])

  .controller("myCtrl1", function($scope){
    var c1 = this;
    c1.msg = "My controller 1 msg";
  })

  .controller("myCtrl2", function($scope){
  })

  .controller("myCtrl3", function($scope){
  })

</script>
</body>
</html>

Second Methods: Accessing through a JSON object. In this method, we will remove c1 in ng-controller of myCtrl1. We have to define $Scope.c1 as JSON object in controller one and in view we can access the model through c1.msg.

<html ng-app="myApp">
<html>
<head>

  <script src="js/angular.min.js"></script>
</head>
<body>
  <div ng-controller="myCtrl1" >
    Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
    <div ng-controller="myCtrl2" >
      Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
      <div ng-controller="myCtrl3" >
        Controller 1 Message Date : <input type="text" ng-model="c1.msg"/>
      </div>
    </div>
  </div>

<script>
  var app = angular.module("myApp", [])
  .controller("myCtrl1", function($scope){
    $scope.c1 = {
      msg : "My controller 1 msg"
    }
  })
  .controller("myCtrl2", function($scope){
  })
  .controller("myCtrl3", function($scope){
  })
</script>
</body>
</html>

Method 3rd:
When we tried to update the specific model object data at a respective child the AngualarJs is creating an isolated model in respective child controller.
We can be solved this issue by using another method by using $parent.

<input type=”text” ng-model=”$parent.msg”/>

Where $parent is a prototype and here we are informing AngualarJs not to look model object at a respective child and asking AngualarJs to look model object at its parent reference when we are updating the model object at
a respective child.

All above methods will not create any isolated model object at it child controller when a child controller update model object of its parents. 

<html ng-app="myApp">
<html>
<head>
  <style>
    div {
      border : 1px solid blue;
      padding: 10px;
      margin: 10px;
    }
  </style>
  <script src="js/angular.min.js"></script>
</head>
<body>
  <div ng-controller="myCtrl1" >
    Controller 1 Message Date : <input type="text" ng-model="msg"/>
    <div ng-controller="myCtrl2" >
      Controller 2 Message Date : <input type="text" ng-model="$parent.msg"/>
      <div ng-controller="myCtrl3" >
        Controller 2 Message Date : <input type="text" ng-model="$parent.$parent.msg"/>
      </div>
    </div>
  </div>

<script>
  var app = angular.module("myApp", [])
  .controller("myCtrl1", function($scope){
    $scope.msg = "My controller 1 msg";
  })
  .controller("myCtrl2", function($scope){
  })
  .controller("myCtrl3", function($scope){
  })
</script>
</body>
</html>

In controller 3 we have to use the double $parent to informing AngularJs to look model of parents parents. It will be difficult for when we have many levels of parent-child relationship.

Methods 4: Using $broadcast and $emit
Using these two we can send information or signal from source to destination controller. We have to define particular source and destination in this methods with respect to nesting. So when it comes to the broadcast source will be parent and destination is a child.

$broadcast: parent to child
$emit : child to parent

In this example when updating data model at a child will create an isolated model at it a child, we have to inform the parent that updating model object at child myCtrl3, the data model object at the parent have to updated in its parent myCtrl2 and its parent myCtrl1.

<html ng-app="myApp">
<html>
<head>
  <script src="js/angular.min.js"></script>
</head>
<body>
  <div ng-controller="myCtrl1" >
    Controller 1 Message Date : <input type="text" ng-model="msg" ng-keyup="toChild()"/>
    <div ng-controller="myCtrl2" >
      Controller 2 Message Date : <input type="text" ng-model="msg"  ng-keyup="toParentAndChild()" />
      <div ng-controller="myCtrl3" >
        Controller 2 Message Date : <input type="text" ng-model="msg" ng-keyup="toParent()"/>
      </div>
    </div>
  </div>

<script>
  var app = angular.module("myApp", [])
  .controller("myCtrl1", function($scope){
    $scope.msg = "My controller 1 msg";

    $scope.toChild = function(){
      $scope.$broadcast("toChild", $scope.msg);
    }
    $scope.$on("toParent", function(event, data){
      $scope.msg = data;
    })

  })
  .controller("myCtrl2", function($scope){
    $scope.toParentAndChild = function(){
      $scope.$emit("toParent", $scope.msg);
      $scope.$broadcast("toChild", $scope.msg);
    };
    $scope.$on("toParent", function(event, data){
      $scope.msg = data;
    });

    $scope.$on("toChild", function(event, data){
      $scope.msg = data;
    })
  })
  .controller("myCtrl3", function($scope){
    $scope.toParent = function(){
      $scope.$emit("toParent", $scope.msg);
    }

  })
</script>
</body>
</html>

We have four methods of updating data model from child to parent, the last methods $broadcast and $emit is slow in performance as update data at controller and pass the information between controller. If we can solve problem when updating data from child to parent with aliasing and $scope.parent then it right choice to do in my opinion.