Scope and rootScope in AngularJS
- 24-07-2022
- Toanngo92
- 0 Comments
In previous articles, we have temporarily understood the MVC structure of AngularJS:
- View: HTML display data
- Model: data to work with the current view
- Controller: logical flow written in angularJS functions, used to add, edit, and delete data
$scope is an object (object) responsible for data communication between the controller and the view of the application, we can understand it as a bridge, when the $scope variable changes, the data in the controller and the view are updated. synchronized . It will be done in the form of an expression, that is, in the model that will be declared in accordance with the specifications, the scope object will pass the corresponding action (function) or data and we can pass events through this object. .
Scopes provides the same expressions as today's template engines, for example to display the username we will declare it as {{username}} and in the controller we just need to assign $scope.username = 'toanngo92' the object This will take a key named username and assign it to view {{username}}.
Mục lục
Scope of $scope
In an AngularJS application, we can have many Controllers, many different $scopes . Going back to the example below:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Example Controller</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script> </head> <body> <div ng-app="examController"> <div ng-controller="headerController"> {{name}} - {{data}} </div> <div ng-controller="mainController"> {{name}} - {{data}} </div> <div ng-controller="footerController"> {{name}} - {{data}} </div> </div> <script> var app = angular.module('examController', []); app.controller('headerController', function($scope){ $scope.name = "This is header"; }); app.controller('mainController', function($scope){ $scope.name = "This is main"; $scope.data = "main data"; }); app.controller('footerController', function($scope){ $scope.name = "This is footer"; }); </script> </body> </html>
We see in the views linked to the corresponding controller that the {{data}} value is different, but each controller, the data property in the variable in each controller is different. This proves that the scope of the $scope variable is only in the corresponding controller.
$rootScope and the hierarchy of $scope
Example #1:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="angular.min.js"></script> <!-- <script src="angular-route.min.js"></script> --> </head> <body ng-app="toanApp"> <div >Data rootscope: {{name}}</div> <div ng-controller="indexController"> <input ng-model="name" value=""/> <p> Data scope {{name}}</p> <button ng-click="changename()" >click</button> </div> <script> var app = angular.module("toanApp",[]); app.run(function($rootScope){ $rootScope.name = "root scope"; }); app.controller( "indexController", function($scope){ // console.log(languages); $scope.name = "controller scope"; $scope.changename = function(e){ $scope.name = "test"; } } ); </script> </body> </html>
Result when printing, and interacting with input
With the above example, we see that we have used a div and called the model name to the view, but this model does not belong to any controller, we understand below the script layer, through the app.run() method, we initialized a global model named name, so even though it's not in any controller, we can still represent the variable name. and for model name in div structure inside indexController, we see when updating data, model in controller changes but has nothing to do with external model, it makes sense, 2 model names are in $scope and $rootScope even though they have the same name, they are not related in nature
Example #2 :
Now we will change a bit the syntax of the AngularJS code as follows:
In this example, the main difference is that the first JS Controller has a $rootScope parameter, and the second Controller does not handle anything. Run it up, you will see the following interface:
So obviously the code above does not pass the value to $scope in both controllers, but the view still has it? That's because the $rootScope variable. This means that when the application is run, there will be a $rootScope automatically created, $rootScope is the top level so it will cover all $scopes inside it, this is not the same as $scope which is only affect in the controller's scope.
Consider the example below:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Example Controller</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script> </head> <body> <div ng-app="examRootScope"> <div ng-controller="headerController"> {{name}} - {{data}} {{data_global}} </div> <div ng-controller="mainController"> {{name}} - {{data}} </div> <div ng-controller="footerController"> {{name}} - {{data}} </div> </div> <script> var app = angular.module('examRootScope', []); app.controller('headerController', function($scope,$rootScope){ $scope.name = "This is header"; $scope.data= "header data scope"; $rootScope.data = "header data root scope"; }); app.controller('mainController', function($scope){ $scope.name = "This is main"; $scope.data = "main data"; }); app.controller('footerController', function($scope,$rootScope){ $scope.name = "This is footer"; $scope.data = "footer data scope"; $rootScope.data_global = "thuoc tinh dung chung"; }); </script> </body> </html>
Print results to the screen:
Adding some more information in the example above, there are 2 points to pay attention to:
- In the headerController, the two properties $scope.data and $rootScope.data are named the same (data), but when printing the view with an expression, the value will be taken from the data property of the $scope berth, proving if in case the model has the same name, $scope will take precedence over $rootScope
- In the footerController, there is a property named data_global that I set myself, but in the view layer associated with the headerController, I intentionally called this data_global model, but the views are still recognized, this proves the data in $ rootScope is global (can be used to share or pass data between controllers)
Nested Scope (nested scope)
In angularJS, we have the concept of nested controllers, similarly nested scopes, with this situation need to be very careful because there will be many situations where it is impossible to distinguish which scope is using. Consider the example below:
<!DOCTYPE html> <html lang="en" ng-app="myApp"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.8.2/angular.min.js"></script> </head> <body ng-controller="parentController"> What controller am I? {{parentVariable}} <div ng-controller="childController"> What controller am I? {{childVariable}} {{parentVariable}} <button ng-click="childFunction()"> Click me to override! </button> </div> </body> <script> var app = angular.module('myApp', []); app.controller('parentController', function ($scope) { $scope.parentVariable = "I'm the parent"; }); app.controller('childController', function ($scope) { $scope.childVariable = "I'm the child"; $scope.childFunction = function () { $scope.parentVariable = "Parent changed!"; console.log($scope); }; }); </script> </html>
Result when running test and clicking override button:
The problem here, when logging the $scope variable, the parentVariable data has changed, but the parentVariable in the parentController is not updated, this problem will be really confusing and inconvenient in the coding process, so advice For you, you should name variables clearly, if you have to use nested controllers, you should learn the structure carefully to avoid unexpected errors.
Also, if we talk about scope, there will be a lot of problems, but in terms of approach, these concepts are the things we need to grasp before we go into making a real application with angularjs.