Introduction to AngularJS

AngularJS is a structural framework (built using JavaScript and jQuery) that enables you to write a "Single Page Application". SPAs are web applications that run inside of a single HTML page, dynamically updating that page (using AJAX calls) in response to user interactions. Click here to see a list of web sites that have been made using AngularJS.

You begin by referencing the AngularJS code (either by linking to their code that's hosted on a Content Delivery Network or by downloading their files into your project). After laying out your page using HTML and CSS, you utilize AngularJS components to extend HTML's syntax to express your application's functionality clearly and succinctly. Angular's data binding and dependency injection eliminate much of the code you would otherwise have to write.

  1. Introduction to AngularJS (and data binding) Open/Close

    AngularJS is a Model View Controller framework that has its own custom directives (which, syntactically, look just like HTML attributes). These directives provide a lot of "automatic" functionality (as we will soon see). Run this to see some really simple Angular code. Click Here to open/close the window that displays a formatted copy of that code.

        <!DOCTYPE html>
        <html>
            <head>
                <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
            </head>
            <body>
                <div ng-app="">
                    <p>Input something in the input box:</p>
                    <p>Name: <input type="text" ng-model="name"></p>
                    <p>{{name}}</p>
                    <p>The "name" ng-model element is "bound to" the {{name}} expression.</p>
                </div>
            </body>
        </html>   
     Run It                

    In the program (that you should have opened just above), we can see several things.

    • A script tag references the Angular JavaScript library from a CDN (Content Delivery Network). Another option would be to download the code, but I think it's better to reference a CDN.
    • The "ng-app" directive (actually should be "data-ng-app" to be valid HTML) defines the area within the page that you are "sharing with" Angular (having it provide functionality).
    • The "ng-model" directive (in the above code) identifies a textbox as being part of the model (or data). An "ng-bind" directive or the {{ }} expression notation (as was used here) lets you bind a view to the model. With data binding, whenever the model changes, the view automatically changes. Type some text into the textbox and note that it immediately changes the expression (the view).
  2. Angular Controllers Open/Close

    One of the goals of Angular is to component-ize things (the opposite of having everything with global scope). This avoids name conflicts and makes code more reliable/easier to maintain. In Angular, you can define a function (usually unnamed) to control any DOM element that has an "ng-controller" attribute. When you define that function, one of its parameters must be named $scope (no other name, an Angular requirement). The controller function can access/modify any "ng-model" DOM element that is a child of the "ng-controller" element by prefixing the "ng-model" name with "$scope." $scope is simply an object that you (the HTML coder) share with the Angular framework - you can access/modify any properties of the $scope object and so can the framework.

    Run this page which shows how a controller function is limited to controlling just a particular DOM element (and it's children). Modify this code in the following ways:
    • Add a second model element to the 'myCtrl' (for example add an "age" textbox) and assign it a model name. Add some code in the 'myCtrl' controller to set the value of this new model element.
    • Next, make the 'myCtrl' div be a child of the 'myApp' div (right now, they are one and the same div). Make sure it still works.
    • Change the name of the ng-controller attribute from 'myCtrl' to something more self documenting, like 'personCtrl'. Test.
    • Now add a second child div to the 'myApp' div. Assign it an ng-controller attribute like 'sportsCtrl'. Inside of this div, add a model element perhaps named 'sport'. Add a second controller function to your code and have it control the new 'sportsCtrl' div. Add some code inside of this function - to set the value of the 'sport' model element. Test.

    When you have completed the above modifications, Click Here to open/close the code window (that should match the changed you just made) and examine the elements within that code:

        <!DOCTYPE html>
        <html>
            <head>
                <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
            </head>
            <body>
                <div ng-app="myApp">
                    <div ng-controller="personCtrl">
                        Name: <input ng-model="name">
                        Age: <input ng-model="age">
                    </div>
                    <div ng-controller="sportCtrl">
                        Sport: <input ng-model="sport">
                    </div>
                </div>
    
                <script>
                    var app = angular.module('myApp', []);
                    app.controller('personCtrl', function($scope) {
                        // This (unnamed) function can access/modify any ng-model elements in the 'personCtrl' ng-controller element 
                        // (name and age). These ng-model elements (name and age) are "bound to" properties of the $scope object 
                        // which is shared between Angular and this controller function. If the controller function changes the value 
                        // of $scope.name or $scope.age (as is done here), the model values (in the UI) immediately reflect this change. 
                        // If the UI values are changed by the user, the controller can access these values ($scope.name, $scope.age).
                        $scope.name = "John Doe";
                        $scope.age = 23;
                    });
                    app.controller('sportCtrl', function($scope) {
                        // This unnamed function can access/modify any ng-model elements in the 'sportCtrl' ng-controller element.
                        $scope.sport = "volleyball";
                        $scope.name = "sally"; // has no effect, name is in the other controller
                    });
                </script>
           </body>
        </html>     
     Run It
    • User Interface. The ng-app DOM element ('myApp') defines the user interface that will be shared by you (the HTML coder) and Angular (the framework). Inside that shared user interface element are two ng-controller DOM elements (both inside of 'myApp'). The "personCtrl" ng-controller (DOM element) contains two ng-model elements (name and age) and the "sportCtrl" ng-controller contains one ng-model element (sport).
    • JavaScript. With this line of code, we get a reference to the Angular framework object that will be limited to the DOM element "myApp" (and its children).
          var app = angular.module('myApp', []);
      These lines of code define an (unnamed) function that can access/modify any of the model elements in the 'personCtrl' div (name and age). Any code that needs to access name and/or age must reside "inside of" this unnamed function.
          app.controller('personCtrl', function($scope) {
              $scope.name = "John Doe";
              $scope.age = 23;
          }); 
    • Make a planned mistake. In the 'sportCtrl' controller function, try to modify the 'name' model element. You'll see that this has no effect because the 'sportCtrl' function is limited (by design) to only the model elements that are in the 'sportCtrl' div.
    • Make another planned mistake. Put the 'sportCtrl' div outside of the 'myApp' div. The 'sportCtr' controller function can no longer access the model elements of the 'sportCtrl' div (by design) because Angular is only sharing with you the elements within the 'myApp' div.
  3. The "ng-repeat" Directive Open/Close

    For more practice with controllers and to learn about the very useful "ng-repeat" directive, run this page. Note that the controller function adds an array ("names") to the $scope object, then the controller's ng-controller (div) utilizes the array values in a "ng-repeat" directive. Each of the values in array $scope.names (Emil, Tobias, Linus) is shown as a <li> (list item) tag. Modify the code a bit (maybe change the array values, perhaps make the names be <h4> tags instead of <li> tags) to be sure you understand this directive. Here is the sample code:

        <!DOCTYPE html>
        <html>
            <head>
                <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
            </head>
            <body>
                <div ng-app="myApp" ng-controller="myCtrl">
                    <ul>
                        <li ng-repeat="x in names">{{x}}</li>
                    </ul>
                </div>
                <script>
                    var app = angular.module('myApp', []);
                    app.controller('myCtrl', function($scope) {
                        $scope.names = ["Emil", "Tobias", "Linus"];
                    });
                </script>
             </body>
        </html>               
     Run It
  4. Angular $http (Get) Service Open/Close

    An Angular service is just functionality provided by Angular, that you can utilize. Thereare about 30 Angular services, including $location (lets you navigate to a new location) and $setInterval (allows you to do something repeatedly), but probably the most important service is $http. Run this page to see how you can use the Angular $http Service to make an AJAX Call. The code below has a success function as well as an error function. Both of these functions write the response object to the console (after indicating success or failure), so that you can discover all the response property/values (like response.statusText) that can be helpful if something goes wrong. In order for this particular code to work properly, you need a file named "welcome.html" that contains just a few words like "hello there" (not a fully formed html page).

    Here is the index file:

        <!DOCTYPE html>
        <html>
            <head>
                <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
            </head>
            <body>
                <h3>Must "Run" not "View" because this code uses $http (which needs apache)</h3>
                <div ng-app="myApp" ng-controller="myCtrl"> 
                    <p>Today's welcome message is: <strong> {{myWelcome}}</strong> </p>
                </div>
                <p>
                    The 'myCtrl' controller function (at page load time) calls the $http service to make an AJAX call. 
                    "myWelcome" is added as a property of $scope and is set to the AJAX response. Due to binding, the 
                    {{myWelcome}} expression shows that response.
                </p>
                <p>Press F12 to see the Chrome console messages.</p>
    
                <script src='http_get_app.js'> </script>
            </body>
        </html>           
     Run It

    Here is the JavaScript file

        var app = angular.module('myApp', []);
    
        app.controller('myCtrl', function ($scope, $http) {
            $http.get("welcome.html").then(
                    function (response) { // success
                        console.log("ajax success");
                        console.log(response);
                        console.log("");
                        $scope.myWelcome = response.data;
                    },
                    function (response) { // error
                        console.log("ajax error");
                        console.log(response);
                        console.log("");
                    }
            ); // closes off "then" function call
        }); // end of def'n of the controller function for 'myCtrl' ng-controller element
                

    And here is the referenced file: "welcome.html"

        Greetings from Angular !  

    Click here for a good reference to the $http service (from angularjs.org). Sally's code reference: 32a_http_svc_AJAX

  5. Using $http (Get) with "ng-repeat" Open/Close

    In the example below, we combine the techniques presented before: $http (get) and "ng-repeat".

    Here is the index file:

        <!DOCTYPE html>
        <html>
            <head>
                <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.1/angular.min.js"></script>
            </head>
            <body ng-app="countryApp">
                <h3>Must "Run" not "View" because this code uses $http (which needs apache)</h3>
                <div ng-controller="CountryListCtrl">
                    <ul>
                        <li ng-repeat="country in countries">{{country.name}}</li>
                    </ul>
                </div>
                <script src="get_with_repeat_app.js"> </script>
            </body>
        </html>        
     Run It

    Here is the JavaScript file

        var countryApp = angular.module('countryApp', []);
    
        countryApp.controller('CountryListCtrl', function ($scope, $http) {
    
            // The "then" (chained function call) takes two parameters: 
            //   * function for success (of ajax call) then 
            //   * function for error (of ajax call).
            $http.get('countries.json').then(
                    function (response) { // what to do if success
                        console.log("ajax success");
                        console.log(response);
                        console.log("");
                        $scope.countries = response.data;
                    },
                    function (response) { // what to do if error
                        console.log("ajax error");
                        console.log(response);
                        console.log("");
                    }
            ); // closes off the parameter list to the "then" function...
        }); // finishes fn def'n for unnamed controller of 'ContryListCtrl' ng-controller element.
    
        /*
         * // Simple GET request example: * https://docs.angularjs.org/api/ng/service/$http
         * 
         * Note: ".then" should be used.
         *       ".success" and ".error" should not be used as they have been deprecated.
         */   

    And here is the referenced file: "countries.json"

        [
          {
            "name": "China",
            "population": 1359821000,
            "flagURL": "//upload.wikimedia.org/wikipedia/commons/f/fa/Flag_of_the_People%27s_Republic_of_China.svg",
            "capital": "Beijing",
            "gdp": 12261
          },
          {
            "name": "India",
            "population": 1205625000,
            "flagURL": "//upload.wikimedia.org/wikipedia/en/4/41/Flag_of_India.svg",
            "capital": "New Delhi",
            "gdp": 4716
          },
          {
            "name": "United States of America",
            "population": 312247000,
            "flagURL": "//upload.wikimedia.org/wikipedia/en/a/a4/Flag_of_the_United_States.svg",
            "capital": "Washington, D.C.",
            "gdp": 16244
          }
        ]  
  6. Angular Sorting and Searching Open/Close

    Now, you can start to see how easy it can be to have fairly sophisticated functionality: data filtering and user sortable columns. The JavaScript file is not much more than a simple $http get. The functionality was achieved by use of just a few angular directives:

    • ng-model="query"
    • ng-click="sortField = 'fieldName'; reverse = !reverse"

    Here is the index file:

        <!DOCTYPE html>
        <html ng-app="personApp">
            <head>
                <meta charset="utf-8">
                <title>Angular.js Example</title>
                <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
            </head>
            <body ng-controller="personController">
                <h3>Sorting and Filtering</h3>
                <p>From NetBeans, select "run" not "view". Click on column headings to sort.</p>
                Search: <input ng-model="query" type="text"/>
                <br/><br/>
                <table>
                    <tr>
                        <th><a href="" ng-click="sortField = 'name'; reverse = !reverse">Name</a></th>
                        <th><a href="" ng-click="sortField = 'gender'; reverse = !reverse">Gender</a></th>
                        <th><a href="" ng-click="sortField = 'age'; reverse = !reverse">Age</a></th>
                    </tr>
                    <tr ng-repeat="person in persons| filter:query | orderBy:sortField:reverse">
                        <td>{{person.name}}</td>
                        <td>{{person.gender}}</td>
                        <td>{{person.age}}</td>
                    </tr>
                </table>
                <script src='sorting_and_filtering_app.js'></script>    
            </body>
        </html>                    
     Run It

    Here is the JavaScript file:
        var personMod = angular.module('personApp', []);
    
        personMod.controller('personController', function ($scope, $http) {
    
            $http.get('persons.json').then(
    
                    function (response) { // what to do if success
                        console.log("ajax success");
                        console.log(response);
                        console.log("");
                        $scope.persons = response.data;
                    },
                    function (response) { // what to do if error
                        console.log("ajax error");
                        console.log(response);
                        console.log("");
                    }
            );
    
            $scope.sortField = 'name';
            $scope.reverse = true;
        });                    

    And here is the referenced file: "persons.json"
        [
            {
                "name": "mickey mouse",
                "gender": "male",
                "age": 82
            }, {
                "name": "minnie mouse",
                "gender": "female",
                "age": 78
            }, {
                "name": "superman",
                "gender": "male",
                "age": 90
            }
        ]                      
  7. Using Angular Routing for Layout (UI Code Reuse) Open/Close

    You can use Angular Routing to handle UI code reuse/common layout. Instead of each page having "include" directives to go and get a navbar and then a footer, you have one "master page" (like Visual Studio) that provides logic about what content to insert, depending on the URL (in the browser's address bar). This approach was used in the code example below.

    index.html Open/Close ||
        <!DOCTYPE html>
        <html>
            <head>
                <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.10/angular.min.js"></script>
                <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.10/angular-route.min.js"></script>
                <link href="styles.css" rel="stylesheet" type="text/css" />
            </head>
            <body ng-app="demoApp">
                <div ng-controller="demoController">
                    <div id='titleNav'>
                        <div id='title'>Angular Routing Parameters</div>
                        <div id='nav'>
                            <div class='navLink'><a href='#home'>Home</a></div>
                            <div class='navLink'><a href='#labs'>Labs</a></div> 
                        </div>
                    </div>
                    <div style='clear:both'></div>
                    <div ng-view="" id='contentArea'>
    
                    </div>
                </div>
                <script src='app.js'></script>
            </body>
        </html>  
     Run It
    app.js Open/Close ||
        var demoApp = angular.module('demoApp', ['ngRoute']);
    
        demoApp.config(function ($routeProvider) {
            $routeProvider.
                    when('/', {
                        templateUrl: 'content_home.html',
                        controller: 'demoController'
                    }).
                    when('/home', {
                        templateUrl: 'content_home.html',
                        controller: 'demoController'
                    }).
                    when('/labs', {
                        templateUrl: 'content_labs.html',
                        controller: 'demoController'
                    }).
                    otherwise({
                        redirectTo: '/'
                    });
        });
    
        // Each routing rule needs a controller, even if the controller doesn't do anything...
        demoApp.controller('demoController', function ( ) {
    
        }); // end of def'n of the controller function 
    content-home.html Open/Close ||
        <h1>This the content of my home page</h1>
        <p>
            I hope you will learn a lot about Single Page JavaScript frameworks like AngularJS.
        </p>                     
    content-labs.html Open/Close ||
    <h1>This the content of my labs page</h1>
    
    <h3>Lab 2 Responsive Design</h3>
    <p>
        I made a really cool layout that looked good in desktop view as well as mobile. 
    </p>
    
    ...                      
    styles.css Open/Close
        body {
            font-family: arial, san-serif;
            margin:0;
            padding:0;
            box-sizing: border-box;
            background-color: #D0FFDD;
        }
        #titleNav {
            font-family: fantasy, san-serif;
            width:100%;
            background-color: #CCCCFF;
            border: 2px solid rgba(200,200,200,0.5);
            min-height: 48px;
            box-sizing: border-box;
        }
        #title{
            float:left;
            font-size: 32px;
            padding: 2px;
            padding-left:8px;
            box-sizing: border-box;
        }
        #nav {
            float:right;
        }
        .navLink {
            background-color: #DDDDDD;
            font-size: 16px;
            padding: 13px;
            margin-left: 4px;
            float:left;
            box-sizing: border-box;
        }
        .navLink a {
            text-decoration: none;
        }
        #contentArea {
            padding: 12px;
        }                      

    Here are the important points about the (5 file) code example (just above):

    • Since index.html will be using routing, it needs the Angular Routing JavaScript reference:
      <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.10/angular-route.min.js"></script>
      • index.html is just a simple layout page, complete from title/nav through footer, except it has an empty content area with the "ng-view" attribute assigned. The ng-view element is the one that will receive what the router provides.
      • The nav bar links (href attributes) in index.html are unusual; instead of href='home.html' and href='labs.html', it has href='#/home' and href='#/labs'.
    • You'll also notice (when you run the sample code) that the URLs in the address bar are unlike the file names you usually see.
      • When you run index.html, you'll see this at the right of the URL in the browser:
        projectFolder/index.html#/
      • If you enter just the folder name into the address bar, the URL changes to
        projectFolder/#/
      • If you click on one of the nav bar links (home or labs), you'll see one of these two URLs in the browser:
        projectFolder/index.html#/home -or-
        projectFolder/index.html#/labs
    • The actual routing work is handled in apps.js by the simple code below. It chains some number of "when" function calls, each taking a URL pattern and an object that specifies (templateUrl property) a file that holds the HTML snippet code that is to be passed into the "ng-view" element (our contentArea).
  8. Angular Routing Using Parameters Open/Close

    Assume that you want to show a detailed view of a list element whenever a user clicks on that element from a list. We can do this nicely using Angular routing.

    Here is the index file:

        <!DOCTYPE html>
        <html>
            <head>
                <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.10/angular.min.js"></script>
                <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.2.10/angular-route.min.js"></script>
                <link href="styles.css" rel="stylesheet" type="text/css" />
            </head>
            <body ng-app="demoApp">
                <div ng-controller="personController">
                    <div id='titleNav'>
                        <div id='title'>Angular Routing for Navigation</div>
                    </div>
                    <div style='clear:both'></div>
    
                    <div ng-view="" id='contentArea'> </div>
                    <br/>
                    {{errorMsg}}
                </div>
                <script src='person_app.js'></script>
            </body>
        </html>                    
     Run It

    Here is the JavaScript file:

        var demoApp = angular.module('demoApp', ['ngRoute']);
    
        demoApp.config(function ($routeProvider) {
            $routeProvider.
                    when('/', {
                        templateUrl: 'person_list.html',
                        controller: 'personController'
                    }).
                    when('/list', {
                        templateUrl: 'person_list.html',
                        controller: 'personController'
                    }).
                    when('/:personId', {
                        templateUrl: 'person_detail.html',
                        controller: 'personDetailController'
                    }).
                    otherwise({
                        redirectTo: '/'
                    });
        });
    
        demoApp.controller('personDetailController', function ($scope, $http, $routeParams) {
            console.log("personDetailController");
            console.log($routeParams);
            $scope.personId = $routeParams.personId;
            var jsonFile = "person_" + $routeParams.personId + ".json";
    
            $http.get(jsonFile).then(
                    function (response) { // this function will run if http.get success
                        console.log("ajax success");
                        console.log(response);
                        console.log("");
                        $scope.person = response.data;
                        $scope.errorMsg = "";
                    },
                    function (response) { // this function will run if http.get error
                        console.log("ajax error");
                        console.log(response);
                        console.log("");
                        if (response.status == "403") {
                            $scope.errorMsg = "$http.get: file not found.";
                        } else {
                            $scope.errorMsg = "Error: " + response.status;
                        }
    
                    } // end of error fn
            ); // closes off "then" function call
    
        });
    
        demoApp.controller('personController', function ($scope, $http) {
            $http.get("persons.json").then(
                    function (response) { // this function will run if http.get success
                        console.log("ajax success");
                        console.log(response);
                        console.log("");
                        $scope.persons = response.data;
                        $scope.errorMsg = "";
                    },
                    function (response) { // this function will run if http.get error
                        console.log("ajax error");
                        console.log(response);
                        console.log("");
                        if (response.status == "403") {
                            $scope.errorMsg = "$http.get: file not found.";
                        } else {
                            $scope.errorMsg = "Error: " + response.status;
                        }
    
                    } // end of error fn
            ); // closes off "then" function call
        }); // end of def'n of the controller function                     

    Here is the HTML snippet file: "person_list.html"

        <h2>Person List</h2>
    
        <table>
            <tr>
                <th><a href="" ng-click="sortField = 'id'; reverse = !reverse">Id</a></th>
                <th style="text-align: left"><a href="" ng-click="sortField = 'name'; reverse = !reverse">Name</a></th>
                <th><a href="" ng-click="sortField = 'gender'; reverse = !reverse">Gender</a></th>
                <th><a href="" ng-click="sortField = 'age'; reverse = !reverse">Age</a></th>
            </tr>
            <tr ng-repeat="person in persons| filter:query | orderBy:sortField:reverse">
                <td>
                    <a href="#/{{person.id}}">{{person.id}}</a>
                </td>
                <td>{{person.name}}</td>
                <td>{{person.gender}}</td>
                <td>{{person.age}}</td>
            </tr>
        </table>
    
        <ul>
            <li>
                Click column headings to sort.
            </li>
            <li>
                Click Id for person detail.
            </li>
        </ul>

    Here is the HTML snippet file: "person_detail.html"

        <h2>Person Detail</h2>
    
        <table>
            <tr>
                <td>Id</td>
                <td>{{person.id}}</td>
            </tr>
            <tr>
                <td>Name</td>
                <td>{{person.name}}</td>
            </tr>
            <tr>
                <td>Gender</td>
                <td>{{person.gender}}</td>
            </tr>
            <tr>
                <td>Age</td>
                <td>{{person.age}}</td>
            </tr>
        </table>   
        <p>
            << <a href="#/list">back to list</a>
        </p>

    Here is the referenced JSON file: "persons.json"

        [
            {
                "id": 2,
                "name": "mickey mouse",
                "gender": "male",
                "age": 11
            }, {
                "id": 4,
                "name": "minnie mouse",
                "gender": "female",
                "age": 9
            }, {
                "id": 8,
                "name": "superman",
                "gender": "male",
                "age": 35
            }
        ]         

    Here is an example of the three files I created (that represent an actual json call for a specific person): person_2.json, person_4.json, and person_8.json:

        {
            "id": 2,
            "name": "mickey mouse",
            "gender": "male",
            "age": 11
        }                     

    And finally, the style sheet Open/Close

        body {
            font-family: arial, san-serif;
            margin:0;
            padding:0;
            box-sizing: border-box;
            background-color: #D0FFDD;
        }
        #titleNav {
            font-family: fantasy, san-serif;
            width:100%;
            background-color: #CCCCFF;
            border: 2px solid rgba(200,200,200,0.5);
            min-height: 48px;
            box-sizing: border-box;
        }
        #title{
            float:left;
            font-size: 32px;
            padding: 2px;
            padding-left:8px;
            box-sizing: border-box;
        }
        #contentArea {
            padding: 12px;
        }
        th {
            background-color:#BBBBBB;
            padding: 3px 6px;
        }
        th a {
            color:white;
            text-decoration: none;
        }
        td {
            background-color: rgba(240,240,240,0.8);
            padding: 6px 6px; /* top/bottom then left/right */
        }
        li {
            line-height: 1.4em;
            margin-left: -12px;
        }   
  9. Dependency Injection Open/Close

    Angular is all about limiting the scope, for example, so that one controller cannot "clobber" any values or functions of another controller. This is great, but what if you actually want to have two controllers share some code or some values? That's where you need to use "Dependency Injection". Here is a simple example where two controllers share (basically) a class - you can add private variables, public methods, etc.

        <!DOCTYPE html>
        <html>
            <head>
                <title>Angular1 Dependency Injection</title>
                <meta charset="UTF-8">
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
    
                <!-- Recommended CDNs for Angular 1 (Spring 2017) -->
                <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
                <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular-route.min.js"></script>
    
                <!-- Huge thank you for this simple sample code that explains dependency injection: 
                    http://fdietz.github.io/recipes-with-angular-js/controllers/sharing-code-between-controllers-using-services.html
                -->
    
            </head>
            <body ng-app="MyApp">
                <div ng-controller="MyCtrl">
                    First User is {{firstUser}}
                </div>
                <div ng-controller="AnotherCtrl">
                    Last User is {{lastUser}}
                </div>
                <script>
                    var app = angular.module("MyApp", []);
    
                    // A service is just a class with exposed (public) methods.
                    app.factory("UserService", function () {
    
                        // This array is a private property
                        var users = ["Peter", "Daniel", "Nina"];
    
                        // returning an object that contains two methods (first and last)
                        return {
                            first: function () {
                                return users[0];
                            },
                            last: function () {
                                return users[users.length-1];
                            }
                        };
                    });
    
                    app.controller("MyCtrl", function ($scope, UserService) {
                        $scope.firstUser = UserService.first();
                    });
    
                    app.controller("AnotherCtrl", function ($scope, UserService) {
                        $scope.lastUser = UserService.last();
                    });
                </script>
            </body>
        </html>
     Run It

Additional Resources