Angular JS Parent-Child Controller Communication and Best Practice for usage

Abdullah Süha ışık
Orion Innovation techClub
4 min readJan 21, 2022

--

In this article, we will talk about parent-child controller relations in AngularJS. So you should be familiar with it. We are just focusing on a specific topic, on the first version of AngularJS(1.3.16) before Google implemented a new version(Angular 2+).
Dividing your controller in the little pieces has a lot of benefits. Especially, when your controller is too expanded and managing becomes hard. But the passing of data from parent to child or vice versa can be trouble when they both render the same $scope variable in their own HTML.

Using the parent and child controller approach or regular approach (more service) depends on your choice. I support both of them. I am here as a benefit to prevent/avoid issues and to identify how it has assisted you. If you follow the article, you will discover the parent and child controller approach at which scenario that we used.

In our scenario, we have different login pages for different customers into the same app which works for multiple customers, through the config. We didn’t divide it into login controllers before, because of just HTML appearance difference and little logic difference. Some new requests pushed us to divide our login controller into the 2 children components and parent login controller. Indeed, we had 3 login controllers, (loginController.js, aCompanyLoginController.js, and otherCompaniesLoginController.js)

At this point, I want to talk about best practices and our use case for parent-child controller communication in AngularJS. We kept common things onloginController, translate data, error logic, loading spinner, some$scope variable (if they are going to use both of controllers), etc. aCompanyController had to be very different from the past because new request requirements are different but otherCompaniesLoginController can use old codes.

Photo on giphy.com

The error logic would be an issue. Because it is common, so we defined in the parent controller, and all controllers will use it in their own special login method. The errorLogic can be updated to parent and child controllers, if they update directly on $scope.error value, an issue occurs. AngularJS creates a new $scope.error value for every controller. We defined $scope.error on the parent controller, we can access it on the child controller through $scope.error. When we update `$scope.error` on child controller, that creates a new one, and the child controller’s HTML uses it. Indeed, AngularJS starts confused because $scope.error shows several references. We should prevent directly updating common parent $scope .

After some research on Google, there were numerous suggestions that have been made with `$emit `. That was not very cool, and we’ve needed more basic and logical things, and they just focused on one-way communication.(We need two-way communication) Our solution is, when you need to update `$scope` variable, you do it with the encapsulated set method, and it is defined on the parent controller. Any controller can’t directly set $scope variable. They should use the same encapsulated set method, and every HTML content should use the same $scope variable that has the same reference.

I think above is enough for theory, so let me show you a code. I know that was a boring part :)

Photo on giphy.com

Define all common things on loginController.js and start some initial processes if you require them. In our case, we need to fetch translation files.

In the Below code snippets, I will not show all code, just important pieces, so focus on error and spinner logic because these values need to handle. Logics are the same, but two examples are better than one. They can be updated in both controllers and aCompanyController needs to process again for more special things.

Parent loginController.js

loginContoller.js

I created the $setLoadingIcon method on the parent controller. Because my child controllers want to update the same $scope.showLoadingIcon, and they will render on HTML. My main purpose is to handle $scope.showLoadingIcon in a function, guarantee to use the same reference when updating everywhere. Considering this, we will prevent the same variable from creating double references. All controllers are going to use the same $scope.showLoadingIcon.

loginController.js

loginErrorHandler function uses setLoadingIcon to update $scope.showLoadingIcon in parent controller.

aCompanyLoginController.js

Child-controller uses parent’s setLoadingIconmethods, and it updates parent’s $scope.showLoadingIcon through parent-controller’s method. In this way, they both use the same $scope.showLoadingIcon .

We don’t need any specific getter(get method) for this. We can directly access $scope.showLoadingIcon on controller and HTML

Consequently, If you need to handle the common $scope variable both of parent and child controller, wrap it a function. It’s like a kinda setter method on the parent controller. My last word is “ Use Redux guys “ :) I just tried to keep my app’s state well.

--

--