AngularJS Basics: $scope
AngularJS, for the uninitiated, is an open-source front-end framework that is maintained by Google and an active community. It has been around for some time, but the learning curve can be pretty steep as AngularJS encompasses not one language, but two; HTML and Javascript. AngularJS puts the two of these together and exponentially increases your front-end capabilities as opposed to plain old HTML.
If you’re familiar with HTML then that half of the equation is rather straightforward, but the Javascript is where things will take a turn with the inclusion of “$scope”. Scope as a concept typically defines the level of visibility of a variable or object of which there are two, local or global, but in normal Javascript this is not explicitly called upon. In AngularJS, $scope is essentially the middleman between your HTML view and your Javascript Controller. It is viewable by both the HTML and the Javascript and as such can be interacted with by both. In this sense we can say that $scope in Angular is always visible to its controller and the view that invokes it. Child controllers can see their parent’s $scope as well, but their parents cannot see the child’s $scope. It more or less defines visible data in the application but in a slightly more complex way than local versus global.
From here on out, this article will assume you have AngularJS set up properly for your application and that you are working on developing a Javascript controller and HTML view for it.
Before we get into $scope, you must first define the name of your controller if you haven’t already done so. You can define it in your html by opening a <script> block and putting something like this inside of it:
ngApp.controller([controller name], function ($scope, $rootScope) {
[Javascript will go in here]
}
For example:
ngApp.controller(‘primaryController’, function ($scope, $rootScope) {
$scope.displayText = “Hello World!”;
}
$scope contains data and methods for your application as defined by the controller and follows the normal rules of Javascript; we can define variables and methods freely and they will simply be appended to the $scope object. Every controller you define for an AngularJS application will have a $scope. When you want to assign things to $scope, it will follow this syntax:
$scope.[name of variable or method] = [some value];
As an example:
$scope.displayText = “Hello World!”;
To then use this new controller in your html using the “ng-controller” property:
<div ng-controller=”primaryController”>
{{displayText}}
</div>
What if we have multiple controllers that we want to use in a single HTML page? How do we call data and use methods from multiple $scope objects? The first option, which is the most straightforward, is to make use of the “ng-controller” property in the html. By assigning this property the name of the controller you wish to access, you can then have the rest of the block pull form that controller’s scope. For example, let’s say we have a controller called “primaryController” and another called “secondaryController”. If I want to pull the values from a variable called “$scope.displayText” that exists in both, we could code something like this into the HTML:
<div ng-controller=”primaryController”>
{{displayText}}
</div>
<div ng-controller=”secondaryController”>
{{displayText}}
</div>
Another option is to assign values that you want the HTML and other controllers to be able to see to the $rootScope. $rootScope is the parent of all $scope objects, it is the highest level $scope of the application. If you have multiple controllers attempting to work on a single task, and thus create a single set of values for your view to access, this can be a very efficient way of doing so. You would still call this from an assigned controller, but the value can be defined by any other controller. This makes using $rootScope undesirable when working with an Angular application with a wide number of controllers, for which the first option is superior.
Controllers can also communicate between each other’s $scope objects. You can implement this simply by establishing a child controller for a parent controller. To declare a child controller, you need only nest it in the parent controller. The child controller will have its own $scope object that both it and the html can see. The parent’s $scope is inherited by the child and the child can alter the data in the parent’s $scope, but the parent can neither see not access the child’s scope. This means the child can effectively override the parent’s $scope if it creates a variable or function with the same name as one in the parent’s $scope. When that object is called from the child controller it will use the child’s version of it, but the parent will be unchanged, and its own version can be called if you’re working from the parent controller. Note that this is an extremely tight coupling and the child has near-complete influence over the parent, making this somewhat dangerous to use, but it is a fast and straightforward way of having two controllers communicate to each other.
There are other safer ways to communicate between controllers such as the “factory” method, which we will cover in a future post about communication between Angular controllers.