Angular $ parent and $ parent. $ parent is the same controller when using ng-repeat

I would like to understand why when using ng-repeat with a specific controller in a repeat element, the parent element of this element and the grandfather of this element are the same controller. I expected that grandfather would be the parent of the parent controller, and not the same controller.

Here is the code to clarify this

HTML

 <div ng-controller="MainController"> {{name}} <div ng-controller="SecondController"> {{name}} <ul> <li ng-repeat="item in list" ng-controller="ItemController"> {{item.name}} {{$parent.name}} {{myDad}} {{myGrandpa}} </li> </ul> <div ng-controller="ThirdController"> {{name}} {{$parent.name}} {{myDad}} {{myGrandpa}} </div> </div> </div> 

Js

 angular.module('app', []); angular.module('app') .controller('MainController', function($scope) { $scope.name = "MainController"; }) .controller('SecondController', function($scope) { $scope.name = "SecondController"; $scope.list = [ {'name': 'aaa'} ]; }) .controller('ItemController', function($scope) { $scope.name = "ItemController"; $scope.myDad = $scope.$parent.name; $scope.myGrandpa = $scope.$parent.$parent.name; }) .controller('ThirdController', function($scope) { $scope.name = "ThirdController"; $scope.myDad = $scope.$parent.name; $scope.myGrandpa = $scope.$parent.$parent.name; }); 

Here is codepen

+5
source share
3 answers

In Angular, $ scope inherits, not controllers.

Each controller created by the ng controller creates a new $ scope (childScope), which inherits from the $ scope in which it exists. I think you can read this answer to understand how exactly $ scope (prototypical inheritance) is inherited.

Please, you do not need to use $ parent to get the name of the parent region $, for example, if you removed $ scope.name from ItemController and tried to link {{name}} your template will be compiled and linked, and the value {{name}} will be "SecondController" in your example.

As for broadcasting $, you should try to avoid using $ rootScope. $ broadcast, because it will send an event to all areas of $ in your application. I'm not sure what your use case is, but if you want, for example, to execute the method defined in your "MainController", you can simply call it, for example,

 angular.module('app', []); angular.module('app') .controller('MainController', function($scope) { $scope.name = "MainController"; $scope.doSomething = function() { console.log("Do it"); } }) .controller('SecondController', function($scope) { $scope.name = "SecondController"; $scope.list = [ {'name': 'aaa'} ]; }) .controller('ItemController', function($scope) { $scope.name = "ItemController"; $scope.myDad = $scope.$parent.name; $scope.myGrandpa = $scope.$parent.$parent.name; $scope.clickItem = function() { console.log("Item clicked"); $scope.doSomething(); // The method from "MainController" will be executed unless ItemController is isolated } }) .controller('ThirdController', function($scope) { $scope.name = "ThirdController"; $scope.myDad = $scope.$parent.name; $scope.myGrandpa = $scope.$parent.$parent.name; }); 
+2
source

to answer your question, yes, you must use $ rootScope as a message broker on your system.

As for the specifics, this is due to the scope of directives, the best way to process this code (for others who might stumble upon this question) is as follows:

 <div ng-controller="MainController as main"> {{main.name}} <div ng-controller="SecondController as second"> {{second.name}} <ul> <li ng-repeat="item in list" ng-controller="ItemController as item"> {{item.name}} {{second.name}} {{myDad}} {{myGrandpa}} </li> </ul> <div ng-controller="ThirdController as third"> {{name}} {{third.name}} {{myDad}} {{myGrandpa}} </div> </div> </div> 

this alleviates problems with defining the scope and allows access to the correct controller as part of the directive.

0
source

In your comment about what you want to broadcast, you can use such a function and call it child:

 // in MainController: $scope.broadcastMain = function(message) { $scope.$broadcast(message); }; 

This function is then inherited, but closing it will have $scope the same area in which it was created, so you can use $scope.broadcast() to access your children. ( codepen )

0
source

Source: https://habr.com/ru/post/1209941/


All Articles