< AngularJS Tutorial
  Go Top
advertise here!!!

Library || READ MORE || DOWNLOAD PDF || QUESTION ANSWERS || HOME

  • ANGULARJS INTRODUCTION ↓

    AngularJS is a JavaScript framework that is intended to make it easier to implement RIA web applications. When I first started learning AngularJS there were not that many detailed AngularJS tutorials available. That is why I decided to write my own AngularJS tutorial.

    AngularJS is created by Google, which is probably one of the bigger causes of its success. You can find the AngularJS project here:

    http://angularjs.org/

    AngularJS is based on the MVC pattern (Model View Control). Therefore AngularJS separates your RIA application into models, views and controllers. The views are specified using HTML + AngularJS's own template language. The models and controllers are specified via JavaScript objects and JavaScript functions. Thus, the views are specified declaratively, as HTML normally is, and the models and controllers are specified imperatively, as JavaScript normally is.

    If you don't know the difference between declarative and imperative programming, don't worry. It is not important to know before learning AngularJS. Besides, it is pretty simple to find the definition on the web.

    AngularJS Hello World

    Here is a simple "hello world" example made with AngularJS which shows the model, view and controller parts of an AngularJS app:

    <!DOCTYPE html>
    <html lang="en">
    
    
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
    </head>
    
    <body ng-app="myapp">
    
    
    <div ng-controller="HelloController" >
    
        <h2>Hello {{helloTo.title}} !</h2>
    
    </div>
    
    
    <script>
    angular.module("myapp", [])
        .controller("HelloController", function($scope) {
            $scope.helloTo = {};
            $scope.helloTo.title = "World, AngularJS";
        } );
    </script>
    
    
    
    </body>
    
    </html>
    

    In this example the "view" is this part:

    <div ng-controller="HelloController" >
    
        <h2>Hello {{helloTo.title}} !</h2>
    
    </div>
    

    Notice the ng-controller attribute. This attribute tells AngularJS what controller to use with this view. Notice also the {{helloTo.title}} text. This is part of AngularJS's template system. This tells AngularJS to write the "model" value named helloTo.title to the HTML at this location.

    The "controller" is this part:

    <script>
    angular.module("myapp", [])
        .controller("HelloController", function($scope) {
            $scope.helloTo = {};
            $scope.helloTo.title = "World, AngularJS";
        });
    </script>
    

    This code registers a controller function named "HelloController" in the angular module named "myapp". Angular modules will be explained later in this tutorial.

    The $scope parameter passed to the controller function is the "model". The controller function adds a helloTo JavaScript object, and in that object it adds a title field. It is this helloTo.title value from the model which the view writes into the HTML.

    Developing an AngularJS Application From Scratch

    Now that you have seen the model, view and controller parts of an AngularJS application, let us build the above example application from scratch with explanations for each step.

    AngularJS applications are a mix of HTML and JavaScript (as you have already seen) so the first thing we need is an HTML page:

    <!DOCTYPE html>
    <html>
    <head>
    </head>
    
    <body>
    </body>
    </html>
    

    Second, we need to include the AngularJS JavaScript file in the HTML page so we can use AngularJS:

    <!DOCTYPE html>
    <html>
    <head>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
    </head>
    
    <body>
    </body>
    </html>
    

    Remember to check AngularJS's website for the latest version of AngularJS so you do not keep using the version I use in this example.

    Third, we need to tell AngularJS what part of our HTML page contains the AngularJS app. You do so by adding the ng-app attribute to the root HTML element of the AngularJS app. Typically, the root element is either the html element or the body element. In this example I insert the ng-app attribute into the body element:

    <!DOCTYPE html>
    <html>
    <head>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
    </head>
    
    <body ng-app="myapp">
    </body>
    </html>
    

    In this example I set the ng-app value to myapp. This means that all controller functions must be added to the myapp module. In other words, the AngularJS module named myapp contains all the controllers for this AngularJS application. The name myapp is something I have chosen. You can choose your module names freely.

    Fourth, we need a view. A view is a section of HTML which is enclosed in an HTML element. Here is an example:

    <!DOCTYPE html>
    <html>
    <head>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
    </head>
    
    <body ng-app="myapp">
      <div ng-controller="HelloController" >
    
          <h2>Hello {{helloTo.title}} !</h2>
    
          </div>
    </body>
    </html>
    

    In this example the view is the div element and everything inside it. The div element contains ng-controller attribute with the value HelloController. This means, that the controller function used by this view is named HelloController.

    The view div element contains the HTML

        <h2>Hello {{helloTo.title}} !</h2>
    

    This is standard HTML except for the {{helloTo.title}} part. This part tells AngularJS to insert the model value named helloTo.title into the HTML at that location.

    Fifth, we need a controller function. A controller function is a normal JavaScript function which takes a single parameter: The $scope parameter. The $scope parameter is the model object to be used by the controller function and the corresponding view. The controller function can insert data and functions into the model object. The view can then use the data and the functions.

    Here is our little web app with the controller function inserted:

    <!DOCTYPE html>
    <html>
    <head>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
    </head>
    
    <body ng-app="myapp">
      <div ng-controller="HelloController" >
    
          <h2>Hello {{helloTo.title}} !</h2>
    
      </div>
    
    
        <script>
        angular.module("myapp", [])
        .controller("HelloController", function($scope) {
        $scope.helloTo = {};
        $scope.helloTo.title = "World, AngularJS";
        });
        </script>
    
    </body>
    </html>
    

    The controller function is registered in angular via the angular.module(...).controller(...) function call.

    The angular object is a global object created by the AngularJS JavaScript which is included at the beginning of the page.

    Notice the first of the parameters to the angular.module() function call. The value of that parameter is "myapp". This name matches the name specified in the ng-app attribute in the body element. This way AngularJS knows that the controller function being registered belongs to the myapp module, which happens to be the module which this AngularJS application is using (specified in the ng-app attribute in the body element).

    The controller() function call is what registers the controller function itself. The first parameter passed to the controller() function is the name of the controller function. This is the name you refer to in the ng-controller attribute of the view. The second parameter is the controller function itself.

    AngularJS Application Execution

    Now our example application is complete, so let me explain what happens when this page is loaded into the browser.

    First the HTML document is loaded into the browser, and evaluated by the browser. At this time the AngularJS JavaScript file is loaded, the angular global object is created, and your JavaScript which registers controller functions is executed.

    Second, AngularJS scans through the HTML to look for AngularJS apps and views. When AngularJS finds a view it connects that view to the corresponding controller function.

    Third, AngularJS executes the controller functions and update (render) the views with data from the model populated by the controller. The page is now ready.

    Fourth, AngularJS listens for browser events (e.g. input fields being changed, buttons clicked, the mouse moved etc.). If any of these browser events require a view to change, AngularJS will update the view correspondingly. If the event requires that the corresponding controller function is called, AngularJS will do that too. Not all events require the controller function to be called, even if the view is updated as a result of the event.

    That is it. You are now ready to start playing around with your own AngularJS applications. There is a lot more to learn, but that is covered in subsequent texts in this AngularJS tutorial (see top left corner of each page in this tutorial series for a list of topics in the series).

    AngularJS Challenges And Critique

    Despite AngularJS' success it is not without its challenges. AngularJS makes several bold claims about AngularJS on its project page. Personally, I believe some of those claims to be wrong or at least somewhat misguided. It's not like the model used by AngularJS has not been tried before in other incarnations. That is why I have added an AngularJS critique to this AngularJS tutorial series. If you decide to go ahead with AngularJS I would advice you to at least read the critique too. Too many tutorials just praise AngularJS without looking at its weak spots.

  • ANGULARJS VIEWS AND DIRECTIVES INTRO ↓

    In the first text of this tutorial you saw how AngularJS splits an application into views, controllers and models (MVC). This text will dive deeper into how to create AngularJS views.

    Before we start, let me first set up a simple AngularJS application which you can use to play around with the examples in this text:

    <!DOCTYPE html>
    <html>
    <head>
      <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
    </head>
    
    <body ng-app="myapp">
    
      <div ng-controller="MyController" >
          <span></span>
      </div>
    
      <script>
        angular.module("myapp", [])
        .controller("MyController", function($scope) {
          //empty controller function
        });
      </script>
    
    </body>
    </html>
    

    AngularJS Directives

    AngularJS views mix data from the model into an HTML template. You use AngularJS directives to tell AnguluarJS how to mix the data into the HTML template. This text will cover the most commonly used AngularJS directives.

    Interpolation Directive

    The interpolation directive is one of the most fundamental directives in AngujarJS. The interpolation directive inserts the result of an expression into the HTML template. You mark where to insert the expression using the {{ }} notation. Here is an example:

    <div ng-controller="MyController" >
        <span>{{myData.text}}</span>
    </div>
    

    The HTML template is contained within the div element with the ng-controller attribute. Inside the HTML template is a span element, and inside this is an interpolation directive. This directive instructs AngularJS to insert the data value myData.text at the given location.

    The interpolation directive can also insert data returned from functions of the model object. Here is an example:

      <div ng-controller="MyController" >
          <span>{{myData.textf()}}</span>
      </div>
    
      <script>
        angular.module("myapp", [])
        .controller("MyController", function($scope) {
          $scope.myData = {};
          $scope.myData.textf = function() { return "A text from a function"; };
        });
      </script>
    

    In this example the interpolation directive {{myData.textf()}} will call the myData.textf() function on the $scope model object, and insert the text returned from that function into the HTML template.

    The textf() function is inserted into the $scope.myData object inside the controller function, as you can see in the example.

    ng-bind Directive

    The ng-bind directive is an alternative to the interpolation directive. You use it by inserting an ng-bind attribute into the HTML element you want AngularJS to insert data into. Here is an example:

    <div ng-controller="MyController" >
      <span ng-bind="myData.textf()"></span>
    </div>
    

    This will insert the data returned from the myData.text() function into the body of the span element. Notice how the {{ }} are not necessary around the expression inside the ng-bind attribute.

    Escaping HTML From The Model

    If the data obtained from the model contains HTML elements, these are escaped before being inserted into the HTML template. The escaping means that the HTML is displayed as text, and not as HTML.

    This is done to prevent HTML injection attacks. For instance, in a chat application somebody might insert a <script> element with JavaScript into a chat message. If this element was not escaped, anyone seeing the chat message might have the <script> element executed. With the HTML escaping the <script> element will just be displayed as text.

    You can disable the HTML escaping by using the ng-bind-html-unsafe directive, like this:

    <div ng-controller="MyController" >
      <span ng-bind-html-unsafe="myData.textf()"></span>
    </div>
    

    You should be really careful when disabling HTML escaping. Make sure that no HTML is displayed which is not trusted.

    Conditional Rendering

    AngularJS can show or hide HTML depending on the state of data in the model. You do so using a set of AngularJS directives which are created specifically for that purpose. I will cover these directives in the following sections.

    ng-show + ng-hide Directives

    The ng-show and ng-hide directives are used to show or hide an HTML element depending on data in the model. These two directives do the same thing, but are each other's opposites. Here are two examples:

      <div ng-controller="MyController" >
          <span ng-show="myData.showIt"></span>
          <span ng-hide="myData.showIt"></span>
      </div>
    
      <script>
        angular.module("myapp", [])
        .controller("MyController", function($scope) {
          $scope.myData = {};
          $scope.myData.showIt = true;
        });
      </script>
    

    This example creates two span elements. One has an ng-show directive and the other has an ng-hide directive. Both directives look at the myData.showIt boolean variable to determine if they should show or hide the span element. The ng-show directive will show the element if the model value is true, and hide the element if the model value is false. The ng-hide directive will do the opposite: Hide the span element if the model value is true, and show it if the model value is false.

    Notice how the controller function sets the myData.showIt to true. This means that the example above will show the first span element and hide the second.

    The HTML elements (span elements in this case) are hidden using the CSS property display: none;. That means, that the HTML elements are still present in the DOM. They are just not visible.

    ng-switch Directive

    The ng-switch directive is used if you want to add or remove HTML elements from the DOM based on data in the model. Here is an example:

    <div ng-controller="MyController" >
        <div ng-switch on="myData.switch">
            <div ng-switch-when="1">Shown when switch is 1</div>
            <div ng-switch-when="2">Shown when switch is 2</div>
            <div ng-switch-default>Shown when switch is anything else than 1 and 2</div>
        </div>
    </div>
    
    <script>
        angular.module("myapp", [])
        .controller("MyController", function($scope) {
          $scope.myData = {};
          $scope.myData.switch = 3;
        });
    </script>
    

    This example contains a div element with an ng-switch attribute and an on attribute. The on attribute tells which data in the model to switch on.

    Inside the div element are three nested div elements. The first two nested div elements contains an ng-switch-when attribute. The value of this attribute tells what value the model data referenced in the on attribute of the parent div should have, for the nested div to be visible. In this example the first nested div is visible when myData.switch is 1, and the second nested div is visible when myData.switch is 2.

    The third nested div has an ng-switch-default attribute. If no of the other ng-switch-when directives are matched, then the div with the ng-switch-default attribute is shown.

    In the example above the controller function sets myData.switch to 3. That means that the nested div with the ng-switch-default attribute will be shown. The two other nested div elements will be removed from the DOM completely.

    ng-if Directive

    The ng-if directive can include / remove HTML elements from the DOM, just like the ng-switch directive, but it has a simpler syntax. Here is an example:

    <div ng-controller="MyController" >
        <div ng-if="myData.showIt">ng-if Show it</div>
    </div>
    
    <script>
        angular.module("myapp", [])
        .controller("MyController", function($scope) {
            $scope.myData = {};
            $scope.myData.showIt = true;
        });
    </script>
    

    The main difference between ng-if and ng-show + ng-hide is that ng-if removes the HTML element completely from the DOM, whereas the ng-show + ng-hide just applies the CSS property display: none; to the elements.

    ng-include Directive

    The ng-include directive can be used to include HTML fragments from other files into the view's HTML template. Here is an example:

    <div ng-controller="MyController" >
        <div ng-include="'angular-included-fragment.html'"></div>
    </div>
    

    This example includes the file angular-included-fragment.html into the HTML template inside the div having the ng-include attribute. Notice how the file name is quoted (single quotes).

    You can include HTML fragments based on conditions. For instance, you can choose between two files like this:

    <div ng-controller="MyController" >
        <div ng-include="myData.showIt &&
                            'fragment-1.html' ||
                            'fragment-2.html'"></div>
    </div>
    
    <script>
        angular.module("myapp", [])
        .controller("MyController", function($scope) {
            $scope.myData = {};
            $scope.myData.showIt = true;
        });
    </script>
    

    This example will include fragment-1.html if myData.showIt is true, and fragment-2.html if myData.showIt is false.

    ng-repeat Directive

    The ng-repeat directive is used to iterate over a collection of items and generate HTML from it. After the initial generation the ng-repeat monitors the items used to generate the HTML for changes. If an item changes, the ng-repeat directive may update the HTML accordingly. This includes reordering and removing DOM nodes.

    Here is a simple ng-repeat example:

    <ol>
       <li ng-repeat="theItem in myData.items">{{theItem.text}}</li>
    </ol>
    
    <script>
        angular.module("myapp", [])
        .controller("MyController", function($scope) {
            $scope.myData = {};
            $scope.myData.items = [ {text : "one"}, {text : "two"}, {text : "three"} ];
        });
    </script>
    

    This example will create an li element for each item in the myData.items array.

    You can also iterate over collections returned from a function call. Here is an example:

    <ol>
       <li ng-repeat="theItem in myData.getItems()">{{theItem.text}}</li>
    </ol>
    
    <script>
        angular.module("myapp", [])
        .controller("MyController", function($scope) {
            $scope.myData = {};
            $scope.myData.items = [ {text : "one"}, {text : "two"}, {text : "three"} ];
            $scope.myData.getItems = function() { return this.items; };
        });
    </script>
    

    And you can iterate over the properties of a JavaScript object using a slightly different syntax:

    <ol>
       <li ng-repeat="(name, value) in myData.myObject">{{name}} = {{value}}</li>
    </ol>
    
    <script>
        angular.module("myapp", [])
        .controller("MyController", function($scope) {
            $scope.myData = {};
            $scope.myData.myObject = { var1 : "val1", var2 : "val3", var3 : "val3"};
        });
    </script>
    
    

    Notice the (name, value) part of the ng-repeat directive. That signals to AngularJS to iterate over the properties of an object. The name parameter will be bound to the property name, and the value parameter will be bound to the property value. The name and value parameters can be output to the HTML template just like any other JavaScript variable or object property, as you can see from the HTML template above.

    Special ng-repeat Variables

    The ng-repeat directive defines a set of special variables which you can use when iterating the collection. These variables are:

    • $index
    • $first
    • $middle
    • $last

    The $index variable contains the index of the element being iterated.

    The $first, $middle and $last contain a boolean value depending on whether the current item is the first, middle or last element in the collection being iterated. An item is "middle" if it is not first nor last. You can use these variables to generate different HTML using e.g. the ng-show / ng-hide, ng-switch, ng-if and ng-include directives described earlier.

    Repeating Multiple Elements

    So far you have only seen how to repeat a single HTML element using ng-repeat. In case you want to repeat more than one HTML element you would have to nest those elements inside a container element, and have the container element have the ng-repeat element, like this:

    <div ng-repeat="(name, value) in myData.myObject">
       <div>{{name}}</li>
       <div>{{value}}</li>
    </div>
    

    Wrapping the element to be repeated in a root element may not always be possible though. Therefore AngularJS has the ng-repeat-start and ng-repeat-end directives which mark which element to start and end the repetition with. Here is an example:

    <ol>
        <li ng-repeat-start="(name, value) in myData.myObject">{{name}}</li>
        <li ng-repeat-end>{{value}}</li>
    </ol>
    

    This example will repeat both of the li elements for each property in myData.myObject.

    Filtering

    Some of the directives covered above support filtering. This section will explain how filtering works.

    The ng-repeat directive can accept a filter like this:

    <div ng-repeat="item in myData.items | filter: itemFilter"></div>
    

    Notice the | filter: itemFilter part of the declaration above. That part is the filter definition. The | filter: part tells AngularJS to apply a filter to the myData.items array. The itemFilter is the name of the filter function. This function has to be present on the $scope object, and it has to return either true or false. If the filter function returns true, then the element from the array is used by the ng-repeat directive. If the filter function returns false, the element is ignored. Here is an example:

    <script>
      angular.module("myapp", [])
        .controller("MyController", function($scope) {
          $scope.myData = {};
          $scope.myData.items  = [ {text : "one"}, {text : "two"}, {text : "three"}, {text : "four"} ];
    
          $scope.itemFilter = function(item) {
            if(item.text == "two") return false;
              return true;
            }
          }
        });
    </script>
    

    Formatting Filters

    AngularJS comes with a set of built-in formatting filters which can be used in conjunction with the interpolation directive, and with ng-bind. Here is a list of the formatting filters:

    Filter Description
    date Formats the variable as a date according to the given date format
    currency Formats the variable as a number with a currency symbol
    number Formats the variable as a number
    lowercase Converts the variable to lowercase
    uppercase Converts the variable to uppercase
    json Converts the variable to a JSON string

    Here is a date filter example:

    <span>{{myData.theDate | date: 'dd-MM-yyyy'}}</span>
    

    This example shows the date filter which can format a JavaScript date object according to the date format pattern given after the | date: part. It is the myData.theDate property that will be formatted as a date. Thus, it has to be a JavaScript date object.

    Here is a number filter example:

    <span>{{myData.theNumber | number: 2}}</span>
    

    This example formats the myData.theNumber variable as a number with 2 decimal places.

    Here are an lowercase and uppercase filter example:

    <span>{{myData.mixedCaseText | lowercase}}</span>
    <span>{{myData.mixedCaseText | uppercase}}</span>
    

    Array Filters

    AngularJS also contains a set of array filters which filters or transforms arrays. These filters are:

    Array Filters:

    Filter Description
    limitTo Limits the array to the given size, beginning from some index in the array. The limitTo filter also works on strings.
    filter A general purpose filter.
    orderBy Sorts the array based on provided criteria.

    Here is a limitTo example:

    <span>{{myData.theText | limitTo: 3}}</span>
    

    This limits the $scope myData.theText variable to a length of 3 characters. If this filter had been applied to an array, the array would have been limited to 3 elements.

    The filter filter is a special filter which can do a lot of different things. In its simplest form it simply calls a function on the $scope object. This function must return true or false. True is returned if the filter accepts the value passed to it. False is returned if the filter cannot accept the value. If the filter cannot accept the value, the value is not included in the array resulting from the filtering. Here is an example:

    <ol>
        <li ng-repeat="item in myData.items | filter:filterArray">
            {{item.text}} : {{$first}}, {{$middle}}, {{$last}}
        </li>
    </ol>
    <script>
        angular.module("myapp", [])
            .controller("MyController", function($scope) {
                $scope.myData = {};
                $scope.myData.items    = 
                    [ {text : "one"}, {text : "two"}, {text : "three"}, {text : "four"} ];
    
                $scope.filterArray = function(item) {
                    if(item.text == "two") return false;
                    return true;
                }
            } );
    </script>
    

    This example calls the filterArray() function which filters out items which has a text property with the value two.

    Here is an orderBy example:

    <ol>
        <li ng-repeat="item in myData.items | orderBy:sortField:reverse">
            {{item.text}} : {{$first}}, {{$middle}}, {{$last}}
        </li>
    </ol>
        
    <script>
        angular.module("myapp", [])
                .controller("MyController", function($scope) {
                    $scope.myData = {};
                    $scope.myData.items    = [ {text : "one"}, {text : "two"}, {text : "three"}, {text : "four"} ];
                    $scope.sortField = "text";
                    $scope.reverse   = true;
                } );
    </script>
    

    The orderBy filter takes a $scope variable as parameter. In this example that variable is named sortField. The value of this variable is the name of the property on the sorted data objects which is used to sort the data objects. In this example the sortField property is set to text which means that the data object's text property is used to sort the data objects.

    The orderBy filter can also take a second $scope variable as parameter. In this example that variable is named reverse. The value of this variable determines if the data objects are to be sorted in their natural order, or the reverse order of that. In this case the reverse variable is set to true, meaning the data objects will be sorted in reverse order.

    Chaining Filters

    It is possible to chain filters by simply putting more filters after each other in the filter section. When chaining filters, the output of one filter is used as input for the next filter in the chain. Here is an example:

    <span>{{myData.theText | limitTo: 5 | uppercase}}</span>
    

    This example first limits the string myData.theText to 5 characters using the limitTo filter, and the converts the 5 characters to uppercase using the uppercase filter.

    Assigning Filter Output To Variables

    It is possible to assign the output of a filter to a temporary variable which you can then refer to later in your view. Here is an example:

    <ol>
        <li ng-repeat="item in filteredItems = ( myData.items | filter:filterArray) ">
            {{item.text}} : {{$first}}, {{$middle}}, {{$last}}
        </li>
    </ol>
    <div>{{filteredItems.length}}</div>
    

    This example assigns the output of the filtering to the filteredItems variable. The example then refers to this variable inside the {{ }} directive under the ol element.

    Implementing Custom Filters

    You can implement your own filters in case the AngularJS filters do not suit your needs. Here is an example:

    <div>Filtered: {{myData.text | myFilter}}</div>
        
        
    <script>
        var module = angular.module("myapp", []);
    
        module.filter('myFilter', function() {
    
            return function(stringValue) {
                return stringValue.substring(0,3);
            };
        });
    </script>    
    

    This example registers a filter with AngularJS which can filter strings. The filter returns the first 3 characters of the string. The filter is registered with the name myFilter. It is this name you will have to use when referencing the filter, as you can see in the beginning of the filter.

    If your filter needs more input parameters, add more parameters to the filter function, and add the parameters after the filter name and a : when referencing it. Here is an example:

    <div>Filtered: {{myData.text | myFilter:2:5}}</div>
    
    <script>
        var module = angular.module("myapp", []);
    
        module.filter('myFilter', function() {
    
            return function(stringValue, startIndex, endIndex) {
                return stringValue.substring(parseInt(startIndex), parseInt(endIndex));
            };
        });
    </script>
    

    Notice how the filter reference (| myfilter:2:5) now has two values after the filter name, each value separated by a colon. These two values are passed to the filter as parameters. Notice also how the filter function now takes two extra parameters named startIndex and endIndex. These two parameters are used to determine which part of the string to return as substring from the filter.

  • ANGULARJS SCOPE HIERARCHY AFFIX ↓

    The $scope object used by views in AngularJS are organized into a hierarchy. There is a root scope, and the root scope has one or more child scopes. Each view has its own $scope (which is a child of the root scope), so whatever variables one view controller sets on its $scope variable, those variables are invisible to other controllers.

    Look at this AngularJS code example:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
    </head>
    
    <body ng-app="myapp">
    
        <div ng-controller="myController1">
    
            {{data.theVar}}
    
        </div>
    
        <div ng-controller="myController2">
    
            {{data.theVar}}
    
        </div>
    
    
        <script>
            var module       = angular.module("myapp", []);
            var myController1 = module.controller("myController1", function($scope) {
                $scope.data = { theVar : "Value One"};
            });
            var myController2 = module.controller("myController2", function($scope) {
                $scope.data = { theVar : "Value Two"};
            });
        </script>
    
    
    </body>
    </html>
    

    This example contains two views, each with their own controller function. Each controller sets the variable data.theVar to different values.

    When this example is executed, the $scope hierarchy will look like this:

    • Root $scope
      • $scope for myController 1
      • $scope for myController 2

    As you can see, the $scope object used by the two controllers are not the same $scope object. That is also why the example above would write out two different values for the data bindings {{data.theVar}} inside the two views. The two controller functions for the views set different values for the data.theVar variable in each their own $scope object.

  • ANGULARJS EVENTS ↓

    AngularJS Event Handling Introduction

    When creating more advanced AngularJS applications, sooner or later your application will need to handle DOM events like mouse clicks, moves, keyboard presses, change events etc. AngularJS has a simple model for how to add event listeners to the HTML you generate from your views. This text will explain this model.

    Before we dive into the event stuff let me just show you a simple AngularJS application which we will use as base for the examples shown in this text:

    <!DOCTYPE html>
    <html lang="en">
    
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
    </head>
    
    <body ng-app="myapp">
    
      <div ng-controller="MyController" >
      </div>
    
      <script>
        angular.module("myapp", [])
                .controller("MyController", function($scope) {
                    $scope.myData = {};
                } );
      </script>
    
    </body>
    </html>
    

    AngularJS Event Listener Directives

    You attach an event listener to an HTML element using one of the AngularJS event listener directives:

    • ng-click
    • ng-dbl-click
    • ng-mousedown
    • ng-mouseup
    • ng-mouseenter
    • ng-mouseleave
    • ng-mousemove
    • ng-mouseover
    • ng-keydown
    • ng-keyup
    • ng-keypress
    • ng-change

    AngularJS Event Listener Examples

    Here is a simple AngularJS event listener directive example:

    <div ng-controller="MyController" >
        <div ng-click="myData.doClick()">Click here</div>
    </div>
    
    <script>
        angular.module("myapp", [])
                .controller("MyController", function($scope) {
                    $scope.myData = {};
                    $scope.myData.doClick = function() {
                        alert("clicked");
                    }
                } );
    </script>
    

    When you click the inner div of the above example, the myData.doClick() function will get called. As you can see in the controller function, the myData object has a doClick() function added to it.

    As you can see, attaching events to HTML DOM elements is not much different from generating the HTML in the first place. The event listener functions called are functions added to the $scope object by the controller function.

    The event listener directives have a special variable named $event which you can use as parameter to the event listener function. The $event variable contains the original browser event object. Here is an example:

    <div ng-controller="MyController" >
        <div ng-click="myData.doClick($event)">Click here</div>
    </div>
    
    <script>
        angular.module("myapp", [])
                .controller("MyController", function($scope) {
                    $scope.myData = {};
                    $scope.myData.doClick = function(event) {
                        alert("clicked: " + event.clientX + ", " + event.clientY);
                    }
                } );
    </script>    
    

    You can also pass other parameters to your event listener functions. Here is an example that adds event listener function to a list of li elements:

    <div ng-controller="MyController" >
        <ul>
            <li ng-repeat="item in myData.items"
                   ng-click="myData.doClick(item, $event)">Click here</li>
        </ul>
    </div>
    
    <script>
        angular.module("myapp", [])
                .controller("MyController", function($scope) {
                    $scope.myData = {};
                    $scope.myData.items = [{ v: "1"}, { v: "2"}, { v : "3"} ];
    
                    $scope.myData.doClick = function(item, event) {
                        alert("clicked: " + item.v + " @ " + event.clientX + ": " + event.clientY);
                    }
    
    
                } );
    </script>    
    

    This example iterates through a list of items, generates li elements from them, and adds click listeners to each li element. Along with the call to the click listener is passed the item JavaScript object the li element was generated based on, along with the click event object ($event).

  • ANGULARJS WATCH, DIGEST AND APPLY ↓

    The AngularJS $scope functions $watch(), $digest() and $apply() are some of the central functions in AngularJS. Understanding $watch(), $digest() and $apply() is essential in order to understand AngularJS.

    When you create a data binding from somewhere in your view to a variable on the $scope object, AngularJS creates a "watch" internally. A watch means that AngularJS watches changes in the variable on the $scope object. The framework is "watching" the variable. Watches are created using the $scope.$watch() function which I will cover later in this text.

    At key points in your application AngularJS calls the $scope.$digest() function. This function iterates through all watches and checks if any of the watched variables have changed. If a watched variable has changed, a corresponding listener function is called. The listener function does whatever work it needs to do, for instance changing an HTML text to reflect the new value of the watched variable. Thus, the $digest() function is what triggers the data binding to update.

    Most of the time AngularJS will call the $scope.$watch() and $scope.$digest() functions for you, but in some situations you may have to call them yourself. Therefore it is really good to know how they work.

    The $scope.$apply() function is used to execute some code, and then call $scope.$digest() after that, so all watches are checked and the corresponding watch listener functions are called. The $apply() function is useful when integrating AngularJS with other code.

    I will get into more detail about the $watch(), $digest() and $apply() functions in the remainder of this text.

    $watch()

    The $scope.watch() function creates a watch of some variable. When you register a watch you pass two functions as parameters to the $watch() function:

    • A value function
    • A listener function

    Here is an example:

    $scope.$watch(function() {},
                  function() {}
                 );
    

    The first function is the value function and the second function is the listener function.

    The value function should return the value which is being watched. AngularJS can then check the value returned against the value the watch function returned the last time. That way AngularJS can determine if the value has changed. Here is an example:

    $scope.$watch(function(scope) { return scope.data.myVar },
                  function() {}
                 );
    

    This example valule function returns the $scope variable scope.data.myVar. If the value of this variable changes, a different value will be returned, and AngularJS will call the listener function.

    Notice how the value function takes the scope as parameter (without the $ in the name). Via this parameter the value function can access the $scope and its variables. The value function can also watch global variables instead if you need that, but most often you will watch a $scope variable.

    The listener function should do whatever it needs to do if the value has changed. Perhaps you need to change the content of another variable, or set the content of an HTML element or something. Here is an example:

    $scope.$watch(function(scope) { return scope.data.myVar },
                  function(newValue, oldValue) {
                      document.getElementById("").innerHTML =
                          "" + newValue + "";
                  }
                 );
    

    This example sets the inner HTML of an HTML element to the new value of the variable, embedded in the b element which makes the value bold. Of course you could have done this using the code {{ data.myVar }, but this is just an example of what you can do inside the listener function.

    $digest()

    The $scope.$digest() function iterates through all the watches in the $scope object, and its child $scope objects (if it has any). When $digest() iterates over the watches, it calls the value function for each watch. If the value returned by the value function is different than the value it returned the last time it was called, the listener function for that watch is called.

    The $digest() function is called whenever AngularJS thinks it is necessary. For instance, after a button click handler has been executed, or after an AJAX call returns (after the done() / fail() callback function has been executed).

    You may encounter some corner cases where AngularJS does not call the $digest() function for you. You will usually detect that by noticing that the data bindings do not upate the displayed values. In that case, call $scope.$digest() and it should work. Or, you can perhaps use $scope.$apply() instead which I will explain in the next section.

    $apply()

    The $scope.$apply() function takes a function as parameter which is executed, and after that $scope.$digest() is called internally. That makes it easier for you to make sure that all watches are checked, and thus all data bindings refreshed. Here is an $apply() example:

    $scope.$apply(function() {
        $scope.data.myVar = "Another value";
    });
    

    The function passed to the $apply() function as parameter will change the value of $scope.data.myVar. When the function exits AngularJS will call the $scope.$digest() function so all watches are checked for changes in the watched values.

    Example

    To illustrate how $watch(), $digest() and $apply() works, look at this example:

    <div ng-controller="myController">
        {{data.time}}
    
        <br/>
        <button ng-click="updateTime()">update time - ng-click</button>
        <button id="updateTimeButton"  >update time</button>
    </div>
    
    
    <script>
        var module       = angular.module("myapp", []);
        var myController1 = module.controller("myController", function($scope) {
     
            $scope.data = { time : new Date() };
    
            $scope.updateTime = function() {
                $scope.data.time = new Date();
            }
    
            document.getElementById("updateTimeButton")
                    .addEventListener('click', function() {
                console.log("update time clicked");
                $scope.data.time = new Date();
            });
        });
    </script>
    

    This example binds the $scope.data.time variable to an interpolation directive which merges the variable value into the HTML page. This binding creates a watch internally on the $scope.data.time variable.

    The example also contains two buttons. The first button has an ng-click listener attached to it. When that button is clicked the $scope.updateTime() function is called, and after that AngularJS calls $scope.$digest() so that data bindings are updated.

    The second button gets a standard JavaScript event listener attached to it from inside the controller function. When the second button is clicked that listener function is executed. As you can see, the listener functions for both buttons do almost the same, but when the second button's listener function is called, the data binding is not updated. That is because the $scope.$digest() is not called after the second button's event listener is executed. Thus, if you click the second button the time is updated in the $scope.data.time variable, but the new time is never displayed.

    To fix that we can add a $scope.$digest() call to the last line of the button event listener, like this:

    document.getElementById("updateTimeButton")
            .addEventListener('click', function() {
        console.log("update time clicked");
        $scope.data.time = new Date();
        $scope.$digest();
    });
    

    Instead of calling $digest() inside the button listener function you could also have used the $apply() function like this:

    document.getElementById("updateTimeButton")
            .addEventListener('click', function() {
        $scope.$apply(function() {
            console.log("update time clicked");
            $scope.data.time = new Date();
        });
    });
    

    Notice how the $scope.$apply() function is called from inside the button event listener, and how the update of the $scope.data.time variable is performed inside the function passed as parameter to the $apply() function. When the $apply() function call finishes AngularJS calls $digest() internally, so all data bindings are updated.

  • ANGULARJS AJAX ↓

    AngularJS AJAX Introduction

    In AngularJS you can send AJAX requests in several different ways. These are:

    • AJAX calls via the $http service.
    • JSONP calls via the $http service.
    • REST type calls.

    Note: So far only the $http service is covered (both normal AJAX and JSONP), but that is enough to get you started using AJAX in AngularJS. The REST API is not necessary to understand to start using AJAX (and personally I am not that big a fan of it - you can do the same just as easily with the $http service).

    The $http Service

    The $http service is the easiest way to send AJAX calls to your web server. Remember, that AJAX calls cannot be sent to a different domain than the domain from which the HTML page making the AJAX calls is loaded. For instance, if the HTML page was loaded from aitechtonic.com then that HTML page can only make AJAX calls back to URLs within the aitechtonic.com domain.

    Here is a full AngularJS application with a single $http AJAX example:

    <!DOCTYPE html>
    <html lang="en">
    
    
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
    </head>
    
    <body ng-app="myapp">
    
      <div ng-controller="MyController" >
        <button ng-click="myData.doClick(item, $event)">Send AJAX Request</button>
        <br/>
        Data from server: {{myData.fromServer}}
      </div>
    
      <script>
        angular.module("myapp", [])
            .controller("MyController", function($scope, $http) {
                $scope.myData = {};
                $scope.myData.doClick = function(item, event) {
    
                    var responsePromise = $http.get("/angularjs-examples/json-test-data.jsp");
    
                    responsePromise.success(function(data, status, headers, config) {
                        $scope.myData.fromServer = data.title;
                    });
                    responsePromise.error(function(data, status, headers, config) {
                        alert("AJAX failed!");
                    });
                }
    
    
            } );
      </script>
    
    </body>
    
    </html>
    

    Notice how the controller function registered with the module takes two parameters: A $scope object (as always) and an extra $http object. The $http object (or "service") is used to make AJAX calls.

    The the $http.get() function returns a "promise" object. This promise object has a success() and an error() function. By calling these functions and pass a function to them as parameter you can control what happens when the AJAX call finishes. If the AJAX call succeeds (the server sends back an HTTP code between 200 and 209), the function passed to the success() function is executed. If the AJAX call fails (all other codes except for redirects), the function passed to the error() method is executed. The succss() and error() functions are covered in more detail later.

    $http Functions

    The $http service has several functions you can use to send AJAX requests. These are:

    • $http.get(url, config)
    • $http.post(url, data, config)
    • $http.put(url, data, config)
    • $http.delete(url, config)
    • $http.head(url, config)

    Notice that the $http.post() and $http.put() functions take a data parameter which contains data to be sent to the server. The rest of the $http functions cannot take a data parameter.

    The data parameter will be converted to a JSON string. This string will be be included in the request body when the HTTP request is sent to the server. AngularJS will consider all properties starting with a $ as private, and thus exclude these from the string. If you need to include properties starting with a $ in the data string, convert the data object to a string yourself using JSON.stringify(data).

    $http as a Function

    You can also use the $http service as a function directly, like this:

    var promise = $http(config);
    

    In this case the URL and HTTP method are also set inside the config object. The config object is explained in the following section.

    The config Parameter

    The config parameter passed to the different $http functions controls the HTTP request sent to the server. The config parameter is a JavaScript object which can contain the following properties:

    • method
    • url
    • params
    • headers
    • timeout
    • cache
    • transformRequest
    • transformResponse

    The method property can be used to set the HTTP method for pthe request. The method is one of either GET, POST, PUT, DELETE or HEAD. This property is normally set implicitly via the function you choose to call on the $http service, so you will rarely need to set this property in practice.

    The url property can be used to set the URL of the AJAX call. This is already provided to the various $http functions, so you will rarely need to set this again in the config object.

    The params property is used to set any additional request parameters to be appended to the URL query string. The params property is a JavaScript object with one property per request parameter to add.

    The headers property is used to set any additional HTTP headers you want sent to the server. The headers property is a JavaScript object with one property per header.

    The timeout property is used to set the timeout for the AJAX call. When the timeout limit is reached, the AJAX call is aborted. The timeout is specified in milliseconds.

    The cache property is used to enable XHR GET request caching.

    The transformRequest property is used to set a function which can transform the request object before it is sent to the server.

    The transformResponse property is used to set a function which can transform the response sent back from the server, before it is passed to your application.

    The success() And error() Functions of The Promise Object

    As mentioned earlier the various AJAX functions on the $http service return a promise object. This promise object has two functions called success() and error(). Each of these two functions take a callback function as parameter. If the AJAX request succeeds, the callback function passed to the success() function is executed. If the AJAX request fails, the callback function passed to the error() function is called.

    Inside the success() and error() function you should set the appropriate values on the $scope object. That is the way to get the data or error message out to the user. Update the $scope object with data, and AngularJS will trigger the HTML template rendering so the data can be made visible to the user.

    Both functions take the following parameters:

    • data
    • status
    • headers
    • config

    The data parameter is the JSON object returned by the server. The $http service assumes that your server sends back JSON.

    The status parameter is the HTTP status code returned by the server along with the response.

    The headers parameter is a function that can be used to obtain any HTTP response headers returned along with the response. You get a header by calling headers([headerName]);. As you can see, the headers() function take an array of header names as parameter. The AngularJS documentation is a bit vague about what the function returns, but I suspect it returns a JavaScript object with one key, value pair for each header, with the header name as the key (property name).

    The config parameter is the configuration object that was used to create the given HTTP request (AJAX call). In other words, the config object which was passed as parameter to the $http ajax function call that created this AJAX call, and thereby this promise object.

    AngularJS & JSONP

    AngularJS's $http service is also capable of sending JSONP requests. The normal AJAX calls can only send requests to URLs within the same domain as the HTML page sending the requests was loaded from. You can get around this with JSONP requests.

    JSONP is short for "JSON with Padding" (I explain why, later). A JSONP request is not sent via the XHR object like AJAX calls normally are. Instead, a <script> element is created and inserted into the HTML page. Here is an example of how such a <script> element could look:

    <script src="http://aitechtonic.com/theService.json?callback=theServiceResponse&p1=v1&p2=v2"></script>
    

    The src attribute contains the URL of the remote service to call with the JSONP call. This URL should include any parameters you need to send to the remote service.

    When the <script> element is inserted into the HTML page, the browser will load the script from the given URL. That enables the remote service to send JavaScript back to your application for execution.

    The JavaScript returned by the remote service should be a function call to an existing JavaScript function in your HTML page. Here is how the returned JavaScript could look:

    theServiceResponse( { name : "John", title : "CEO", company : "BigFatCo" } );
    

    This code makes a function call to the function named theServiceResponse. This function must be present in your HTML page already. Inside this function you process the response sent back from the service.

    When the theServiceResponse() function is called, a JavaScript object is passed to the function as parameter. This JavaScript object contains the response parameters from the service call. Thus, this JavaScript object is generated by the remote service. Whatever the remote service wants to send back to you is what this JavaScript object contains. Seen from the remote service's perspective, that JavaScript object is just JSON like any other JSON sent back to an HTML page. The difference is that this JSON object is wrapped in a function call. This function call is the "padding" part of the "JSON with Padding" name for JSONP.

    You might wonder how the remote service knows the name of the function to wrap the returned JSON in. The answer is, that you pass that name to the remote service along with the other request parameters. The function name is one of the request parameters. By default this parameter name is callback but you will have to check with the concrete service to see what parameter name it expects for the function name.

    In AngularJS the function name is supplied behind the scene by AngularJS, so you don't have to worry about adding it to the URL of the remote service.

    You use JSONP calls via the $http service like this:

    $http.jsonp( url, config );
    

    Like with the AJAX functions the jsonp() function takes a url and a config object. Here is an example of a JSONP call with the url and config objects supplied:

    var url = http://aitechtonic.com/theService.json?callback=JSON_CALLBACK";
    var responsePromise = $http.jsonp( url,
                 {  params : {
                       p1 : "v1"
                      ,p2 : "v2"
                    }
                  }
                );
    
    responsePromise.success(function(data) {
        // do something with the returned JavaScript object
        // ( in the "data" parameter ).
    });
    
    

    This example makes a JSONP call to the service URL http://aitechtonic.com/theService.json. Like with the other AJAX functions of the $http service, the config object can contain a params field. This field should be a JavaScript object containing all the request parameters to append to the URL of the remote service.

    When you call the $http.jsonp() function AngularJS will create <script> element for you, and insert it into your HTML page. AngularJS will also create the final URL of the remote service by appending the parameters passed in the config.params object to the URL.

    The URL passed to the $http.jsonp() function must contain the callback=JSON_CALLBACK parameter. AngularJS will replace the JSON-CALLBACK string with the name of a callback function which AngularJS creates.

    The promise object returned by the $http.jsonp() function has a success() function, just like the other AJAX function call promise objects. Unfortunately we do not have access to the HTTP headers of the response sent back from the server, since that request is handled by the browser internally, when evaluating the <script src="url"> element. That also means that if the JSONP call fails, we have no way of knowing so, since no callback function will get called in that case (no JavaScript to execute from the remote service).

    JSONP Security

    You have to be careful with JSONP calls. When you make a JSONP call. The remote service could send back any JavaScript which would then get executed inside your HTML page. An evil remote service could send back JavaScript which attempts to steal information from your application and sent it to a third party service. Only make JSONP calls to services you trust.

  • ANGULARJS FORMS ↓

    AngularJS Form Handling Introduction

    AngularJS has some features for binding data of HTML form input fields to the model object ($scope). These features makes it easier to work with forms.

    You bind an input field to a model property using the ng-model directive like this:

    <input type="text" id="firstName" ng-model="myForm.firstName">
    

    This binding is two-way, meaning if the $scope.myForm.firstName has a value set inside the corresponding controller function, the input field will start with that value. Additionally, once the user types something into the text field, that value will be copied from the text field into the $scope.myForm.firstName property.

    Here is a full AngularJS form example you can play with:

    <!DOCTYPE html>
    <html>
    <head>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
    </head>
    
    <body ng-app="myapp">
    
    <div ng-controller="MyController" >
        <form>
            <input type="text" name="firstName" ng-model="myForm.firstName"> First name <br/>
            <input type="text" name="lastName"  ng-model="myForm.lastName"> Last name <br/>
        </form>
    
        <div>
            {{myForm.firstName}} {{myForm.lastName}}
        </div>
    </div>
    
    <script>
        angular.module("myapp", [])
                .controller("MyController", function($scope) {
                    $scope.myForm = {};
                    $scope.myForm.firstName = "Jakob";
                    $scope.myForm.lastName  = "aitechtonic";
                } );
    </script>
    
    </body>
    </html>
    

    This example binds the two input fields in the form to the $scope.myForm.firstName and $scope.myForm.lastName properties. The two properties both have a value set in the controller function. These values will be displayed in the input fields when the page is first rendered. When the user types in something in the text fields it will get copied into the these properties too.

    The example also contains two interpolation directives ({{}}). These two directives will insert the value of the myForm.firstName and myForm.lastName below the form fields. When you enter something in the text boxes it will be copied into the myForm.firstName and myForm.lastName properties. From there it will be inserted into the HTML by the two interpolation directives. This data binding happens while the user enters data in the form fields, so the interpolation directives will update the values while typing (this looks cool, but I cannot remember the last time I actually needed this in a web app form).

    Binding Checkboxes

    If you bind a checkbox (<input type="checkbox">) to a model property, the model property will be set to true if the checkbox is checked, and false if not.

    If you need other values instead of true and false inserted into your model, you can use the ng-true-value and ng-false-value directives, like this:

     <input type="checkbox" ng-model="myForm.wantNewsletter"
                            ng-true-value="yes" ng-false-value="no" >
    

    Binding Radio Buttons

    Radio buttons are also easy to bind to model properties. If you have a group of radio buttons, just bind them all to the same model property. The radio button that is chosen will have its value copied into the model property. Here is an example:

    <input type="radio" ng-model="myForm.whichNewsletter" value="weeklyNews">    
    <input type="radio" ng-model="myForm.whichNewsletter" value="monthlyNews">    
    

    Binding Select Boxes

    Binding select boxes to model properties is reasonably straightforward too. Here is an example:

    <div ng-controller="MyController" >
        <form>
            <select ng-model="myForm.car">
                <option value="nissan">Nissan</option>
                <option value="toyota">Toyota</option>
                <option value="fiat">Fiat</option>
            </select>
        </form>
    
        <div>
            {{myForm.car}}
        </div>
    </div>
    
    <script>
        angular.module("myapp", [])
                .controller("MyController", function($scope) {
                    $scope.myForm = {};
                    $scope.myForm.car  = "nissan";
                } );
    </script>
    

    ng-options

    Instead of using static HTML options you can have AngularJS create option elements based on data from the $scope object. You do so using the ng-options directive inside the select element. Here is an example:

    <div ng-controller="MyController" >
        <form>
            <select ng-model="myForm.car"
                    ng-options="obj.id as obj.name for obj in myForm.options">
            </select>
        </form>
    
        <div>
            {{myForm.car}}
        </div>
    </div>
    
    <script>
        angular.module("myapp", [])
            .controller("MyController", function($scope) {
                $scope.myForm = {};
                $scope.myForm.car  = "nissan";
    
                $scope.myForm.options = [
                  { id : "nissan", name: "Nissan" }
                 ,{ id : "toyota", name: "Toyota" }
                 ,{ id : "fiat"  , name: "Fiat" }
                 ];
    
            } );
    </script>
    

    The ng-options directive follows the following format:

    optionBinding expression   dataSource expression
    

    The dataSource expression speficies what data in the $scope object is to be used as data source for the option elements. In the example above, the dataSource expression is this part:

    for obj in myForm.options
    

    It defines obj as each object in the myForm.options array. Thus, an option element will be generated from each element in the myForm.options array in the $scope object.

    The optionBinding expression specifies what properties are to be used as value and label for each option element. In the example above the optionBinding is this part:

    obj.id as obj.name
    

    This defines the obj.id property of each object as the value of each option element generated, and the obj.name property as the label. If you want the value and label to come from the same property, just leave out the as obj.name part (the label part of the expression).

    You can call functions on the $scope object from inside both the optionBinding expression and dataSource expression. Here is an example:

    obj.id as getLabelName(obj) for obj in getOptionArray()
    

    This example will use the value returned from the getLabelName(obj) function call as label, and will iterate the objects returned by the getOptionArray() function call.

    You can create option groups ( <optgroup> HTML elements with option elements inside) by adding a group by section to the optionBinding expression. Here is an example:

    obj.id as obj.name group by obj.type
    

    This example will group the generated option elements into optgroup elements using the obj.type property to determine which option elements to group together. Objects with the same value in the obj.type property will be grouped into the same optgroup element.

    You can also iterate the properties of an object instead of iterating an array of objects. Here is an example:

    propName as propValue for (propName, propValue) in objectWithProperties
    

    This example will bind the property name as the option element value and the property value as the label, of all properties in the $scope.objectWithProperties object.

    Empty Options

    If the value set for a select box in the $scope object by the controller function does not match a value attribute of any of the option elements, AngularJS inserts an empty option element in the select box.

    You can set a label for this empty option element by inserting an option element in the HTML, like this:

        <form>
            <select ng-model="myForm.car"
                    ng-options="obj.id as obj.name for obj in myForm.options">
                <option value="">Please choose a car</option>
            </select>
        </form>
    

    Selecting Multiple Options

    If you need a select box that enables the user to choose multiple options, you need to insert the multiple="true" attribute inside the <select> element.

    Once you enable multiple option selection, the data binding changes. Instead of binding the <select> element to a single string value, it is now bound to an array of values. Thus, you also set the selected values using an array. Here is an example showing that:

    <div ng-controller="MyController" >
        <form>
            <select multiple="true" ng-model="myForm.car"
                    ng-options="obj.id as obj.name for obj in myForm.options">
            </select>
        </form>
    
        <div>
            {{myForm.car}}
        </div>
    </div>
    
    <script>
        angular.module("myapp", [])
            .controller("MyController", function($scope) {
                $scope.myForm = {};
                $scope.myForm.car  = ["nissan"];
    
                $scope.myForm.options = [
                  { id : "nissan", name: "Nissan" }
                 ,{ id : "toyota", name: "Toyota" }
                 ,{ id : "fiat"  , name: "Fiat" }
                 ];
    
            } );
    </script>
    

    Form Validation

    AngularJS has a set of form validation directives you can use. AngularJS validates form fields before copying their value into the $scope properties to which the form fields are bound. If a form field is invalid, its value is not copied into the $scope property it is bound to. Instead the corresponding $scope property is cleared. That is done to prevent the $scope properties from containing invalid values.

    Each of the form validating directives are covered in the following sections.

    ng-minlength + ng-maxlength

    The ng-minlength and ng-maxlength form validation directives can be used to validate the length of data entered in a form field. Here is an example:

    <div ng-controller="MyController" >
        <form>
            <input type="text" id="name" ng-model="myForm.name" ng-minlength="5" ng-maxlength="12"> Name <br/>
        </form>
    
        <div>
            {{myForm.name}}
        </div>
    </div>
    
    <script>
        angular.module("myapp", [])
                .controller("MyController", function($scope) {
                    $scope.myForm = {};
                    $scope.myForm.name = "Jakob aitechtonic";
                } );
    </script>
    

    This example sets the ng-minglength to 5 and ng-maxlength to 12. That means that if the text in the input field is less than 5 or more than 12 characters long, the value from the input field will not be copied into the $scope.myForm.name property. You can try this example yourself and see what happens.

    Notice the div element which displays the value of the $scope.myForm.name. This wil show you what value was copied from the text field into the $scope.myForm.name property. Notice how it is empty when the text field contains less than 5 or more than 12 characters.

    ng-pattern

    The ng-pattern directive can be used to validate the value of an input field against a regular expression. Here is an example:

    <input type="text" id="name" ng-model="myForm.name" ng-pattern="/^\d+$/"> Name <br/>
    

    The regular expressions must follow the JavaScript regular expression syntax. This example defines a regular expression that matches strings of digits containing at least 1 digit.

    ng-required

    The ng-required directive checks if the value of the form field is empty or not. Actually, you just use the required attribute of HTML5, and AngularJS detects it automatically.

    Checking Field Validation State

    If you give the <form> element a name attribute, then the form will be add to the $scope object as a property. Here is an example:

      <form name="myFormNg" ng-submit="myForm.submitTheForm()" >
      ...
      </form>    
    

    When you call a function on the $scope object (a function added to the $scope object by your controller function), you can access the ngFormController object via its name, like this:

    $scope.myFormNg
    

    If you add a name attribute to the form fields inside the form, their ngModelController objects will be accessible as properties on the ngFormController object. Here is an example:

      <form name="myFormNg" ng-submit="myForm.submitTheForm()" >
        <input name="firstName" type="text" ng-model="myForm.firstName">
      </form>    
    

    You can now access the ngModelController of the firstName input field like this:

    $scope.myFormNg.firstName
    

    Both ngFormController and ngModelController objects contain a set of properties that tell if the form or input field is valid. The properties are:

    PropertyDescription
    $pristine    True if the form has not been changed (no form fields has changed), false if some fields have been changed.
    $dirty The reverse of $pristine - false if the form has not been changed - true if it has.
    $valid True if the form field (or the whole form = all form fields) is valid. False if not.
    $invalid The reverse of the $valid - false if the field (or all fields in the form) is valid, true if the field (or a single field in the for) is invalid.

    You can use these properties to set a matching CSS class on the input fields. Here is an example :

    <style>
        .fieldValid {
            border: 1px solid #00ff00;
        }
        .fieldInvalid {
            border: 1px solid #ff0000;
        }
    </style>
    
    <div ng-controller="MyController" >
        <form name="myFormNg" >
            <input type="text" ng-class="myForm.getFormFieldCssClass(myFormNg.name)"
                   id="name" name="name" ng-model="myForm.name" ng-minlength="2"> Name <br/>
        </form>
    </div>
    
    <script>
        angular.module("myapp", [])
                .controller("MyController", function($scope, $http) {
                    $scope.myForm = {};
    
                    $scope.myForm.getFormFieldCssClass = function(ngModelController) {
                        //console.log("getting css class: " + ngModelController.$valid) ;
                        if(ngModelController.$pristine) return "";
                        return ngModelController.$valid ? "fieldValid" : "fieldInvalid";
                    }
                } );
    </script>
        
    

    Notice the ng-class directive on the input field. This directive calls the myForm.getFormFieldCssClass() function using myFormNg.name as parameter. This is the ngModelController for the name input element. The myForm.getFormFieldCssClass() just returns the matching CSS class as a string.

    You can also use the validation properties to show or hide div elements with validation messages. Here is the form from before, with a div added:

    <div ng-controller="MyController" >
        <form name="myFormNg" ng-submit="myForm.submitTheForm()" novalidate>
        
            <input type="text" ng-class="myForm.getFormFieldCssClass(myFormNg.name)"
                   id="name" name="name" ng-model="myForm.name" ng-minlength="2"> Name <br/>
    
            <div ng-show="myFormNg.name.$invalid">
                You must enter a valid name.
            </div>
        
        </form>
    </div>
    

    Notice the ng-show directive on the div element. This directive uses the value of the myFormNg.name.$invalid validation property to determine if the div should be shown or not.

    Remember that you can access the $pristine, $dirty, $valid and $invalid properties of the ngFormController too. These properties contain the validation state of the whole form. This button code example disables the submit button if the form is invalid:

    <button ng-disabled="myFormNg.$invalid">Submit Form</button>
    

    Submitting Forms

    You can submit a form in two ways:

    • Using a button element with an ng-click attribute.
    • Using an ng-submit attribute (directive) on the form element.

    In both cases a JavaScript function is called on the $scope object. You attach this JavaScript function to the $scope object in your controller function. The JavaScript function should send the data from the form to your server via AJAX.

    Here is a form that uses the ng-click attribute on a button element:

    <div ng-controller="MyController" >
      <form>
        <input type="text" id="name" ng-model="myForm.name" ng-minlength="5" ng-maxlength="12"> Name <br/>
    
        <select ng-model="myForm.car">
          <option value="nissan">Nissan</option>
          <option value="toyota">Toyota</option>
          <option value="fiat">Fiat</option>
        </select>
    
        <button ng-click="myForm.submitTheForm()">Submit Form</button>
      </form>
    
      <div>
        {{myForm.name}}
      </div>
      <div>
        {{myForm.car}}
      </div>
    </div>
    
    <script>
      angular.module("myapp", [])
         .controller("MyController", function($scope, $http) {
           $scope.myForm = {};
           $scope.myForm.name = "Jakob aitechtonic";
           $scope.myForm.car  = "nissan";
    
         $scope.myForm.submitTheForm = function(item, event) {
           console.log("--> Submitting form");
           var dataObject = {
              name : $scope.myForm.name
              ,car  : $scope.myForm.car
           };
    
           var responsePromise = $http.post("/angularjs-examples/json-test-data.jsp", dataObject, {});
           responsePromise.success(function(dataFromServer, status, headers, config) {
              console.log(dataFromServer.title);
           });
            responsePromise.error(function(data, status, headers, config) {
              alert("Submitting form failed!");
           });
         }
    
      });
    </script>
    

    Notice how the ng-click attribute points to the myForm.submitTheForm() function, and notice how the submitTheForm() function is attached to the $scope object inside the controller function.

    Here is the same form using an ng-submit attribute to submit the form:

      <form ng-submit="myForm.submitTheForm()">
        <input type="text" id="name" ng-model="myForm.name" ng-minlength="5" ng-maxlength="12"> Name <br/>
    
        <select ng-model="myForm.car">
          <option value="nissan">Nissan</option>
          <option value="toyota">Toyota</option>
          <option value="fiat">Fiat</option>
        </select>
    
        <input type="submit" value="Submit Form">
    
      </form>
    

    As you can see, the two mechanisms are very similar. They both call a submit function on the $scope object.

  • ANGULARJS TIMEOUT AND INTERVAL AFFIX ↓

    AngularJS has two timer services, $timeout and $interval, which you can use to call functions in your application. The $timeout and $interval services are similar in their functionality to JavaScript's setTimeout() and setInterval() functions (actually belonging to the window object). The functionality of these services is also similar, so I will cover both in this text.

    $timeout

    The $timeout service can be used to call another JavaScript function after a given time delay. The $timeout service only schedules a single call to the function. For repeated calling of a function, see $interval later in this text.

    Injecting $timeout

    To use the $timeout service you must first get it injected into a controller function. Here is an example that injects the $timeout service into a controller function:

    var myapp = angular.module("myapp", []);
    
    myapp.controller("MyController", function($scope, $timeout){
    
    });
    

    Notice the $timeout parameter of the controller function. Into this parameter the $timeout service will be injected by AngularJS, just like any other AngularJS service you would want to use in your controller function.

    Scheduling a Function Call

    Once the $timeout service is injected into your controller function, you can use it to schedule function calls. Here is an example that used the $timeout service to schedule a function call 3 seconds later:

    var myapp = angular.module("myapp", []);
    
    myapp.controller("MyController", function($scope, $timeout){
    
        $timeout(callAtTimeout, 3000);
    
    });
    
    function callAtTimeout() {
        console.log("Timeout occurred");
    }
    

    This example schedules a function call to callAtTimeout() after 3 seconds (3000 milliseconds).

    If you want to call a function on the $scope object, you can do so like this:

    var myapp = angular.module("myapp", []);
    
    myapp.controller("DIController", function($scope, $timeout){
    
        $scope.callAtTimeout = function() {
            console.log("$scope.callAtTimeout - Timeout occurred");
        }
    
        $timeout( function(){ $scope.callAtTimeout(); }, 3000);
    });
    

    Notice the function passed to the $timeout service. This function calls the callAtTimeout() function on the $scope object.

    $interval

    The $interval service is similar in function to the $timeout service, except it schedules a function for repeated execution with a time interval in between.

    Injecting $interval

    To use the $interval service you must have it injected into a controller function. Here is an example that injects the $interval service into a controller function:

    var myapp = angular.module("myapp", []);
    
    myapp.controller("MyController", function($scope, $interval){
    
    });
    

    As you can see, it is very similar to how you inject any other service in AngularJS.

    Scheduling a Repeated Function Call

    Once the $interval service is injected into your controller function, you can use it to schedule repeated function calls. Here is an example that used the $interval service to schedule a function call every 5 seconds:

    var myapp = angular.module("myapp", []);
    
    myapp.controller("MyController", function($scope, $interval){
    
        $interval(callAtInterval, 5000);
    
    });
    
    function callAtInterval() {
        console.log("Interval occurred");
    }
    

    This example schedules a function call to callAtInterval() every 5 seconds (5000 milliseconds).

    If you want to call a function on the $scope object instead, you can do so like this:

    var myapp = angular.module("myapp", []);
    
    myapp.controller("DIController", function($scope, $interval){
    
        $scope.callAtInterval = function() {
            console.log("$scope.callAtInterval - Interval occurred");
        }
    
        $interval( function(){ $scope.callAtInterval(); }, 3000);
    });
    

    The function passed to the $interval service calls the callAtInterval() function on the $scope object.

    Executing $digest() After the Scheduled Function Call

    If the function you schedule for execution makes changes to variables in the $scope object, or make changes to any other variable which your application is watching, your application needs to execute $scope.$digest() after the scheduled function call finishes. Why that is necessary is explained in my tutorial about $watch(), $digest() and $apply().

    By default AngularJS already calls $digest() after the scheduled function call finishes, so you don't have to do that explicitly. You can, however, specify if AngularJS should not call $digest() after the scheduled function call. If, for instance, your scheduled function call only updates an animation but does not change any $scope variables, then it is a waste of CPU time to call $digest() after the function finishes.

    Both $timeout and $interval have a third, optional parameter which can specify if the $digest() method is to be executed after the scheduled function finishes. Actually, the third parameter specifies if the call to the scheduled function should be done inside an $apply() call. Here is an example of how to use this third parameter:

    $interval( function(){ $scope.callAtInterval(); }, 3000, true);
    
    $interval( function(){ $scope.callAtInterval(); }, 3000, false);
    

    These two $interval examples both have a third parameter passed to the $interval service. This parameter can be either true or false. A value of true means that the scheduled function should be called inside an $apply() call. A value of false means that it should not be called inside an $apply() call (meaning $digest() will not get called after the scheduled function finishes).

  • ANGULARJS CUSTOM DIRECTIVES ↓

    Custom Directive Introduction

    AngularJS directives are what controls the rendering of the HTML inside an AngularJS application. Examples of directives are the interpolation directive ( {{ }} ), the ng-repeat directive and ng-if directive.

    It is possible to implement your own directives too. This is what AngularJS refers to as "teaching HTML new tricks". This text will show you how to do that.

    Directive Types

    You can implement the following types of directives:

    • Element directives
    • Attribute directives
    • CSS class directives
    • Comment directives

    Of these, AngularJS recommends that you try to use element and attribute directives, and leave the CSS class and comment directives (unless absolutely necessary).

    The type of a directive determines how the directive is activated. An element directive is activated when AngularJS finds a matching HTML element in the HTML template. An attribute directive is activated when AngularJS finds a matching HTML element attribute. A CSS class directive is activated when AngularJS finds a matching CSS Class. And, a comment directive is activated when AngularJS finds a matching HTML comment.

    A Basic Directive

    You register a directive with a module. Here is an example of how that looks:

    myapp = angular.module("myapp", []);
    
    myapp.directive('div', function() {
        var directive = {};
    
        directive.restrict = 'E'; /* restrict this directive to elements */
    
        directive.template = "My first directive: {{textToInsert}}";
    
        return directive;
    });
    

    Notice the call to the directive() function on the module. When you call this function you can register a new directive. The first parameter to the directive() function call is the name of the directive to register. This name is what you use in your HTML templates when you want to activate the directive. In this example I have used the name 'div' which means that the directive is activated every time an HTML element named div is found in the HTML template.

    The second parameter passed to the directive function is a factory function. This function should return a directive definition when invoked. AngularJS will invoke this function to obtain a JavaScript object which contains the definition of the directive. If you look inside the function in the above example you will see that it does indeed return a JavaScript object.

    The JavaScript object returned from the factory function has two properties: A restrict field and a template field.

    The restrict field is used to set if the directive should be activated by a matching HTML element, or an element attribute. By setting restrict to E you specify that only HTML elements named div should activate the directive. By setting restrict to A you specify that only HTML attributes named div should activate the directive. You can also use a value of AE which will match both HTML element names and attribute names.

    The template field is an HTML template that will replace the content of the matched div element. It will work as if the content of the matched div element had not been there, and instead this HTML template had been located in the same place.

    Imagine that your HTML page has this HTML:

    <div ng-controller="MyController" >
        <div>This div will be replaced</div>
    </div>
    

    Then the added directive would be activated when AngularJS finds the inner div element. Instead of this div element, this HTML will be inserted:

    My first directive: {{textToInsert}}
    

    As you can see, this HTML contains an interpolation directive ({{textToInsert}}). AngularJS will interpret this HTML again, so that the interpolation directive actually works. The value of the $scope.textToInsert property will be inserted at this point in the HTML.

    The template and templateUrl Properties

    The easiest way to create your own directives is as shown in the example above. Your directive is intended to generate HTML, and you put that HTML inside the template attribute of the directive definition object. Here is the directive definition repeated from earlier, with the template string marked in bold:

    myapp = angular.module("myapp", []);
    
    myapp.directive('div', function() {
        var directive = {};
    
        directive.restrict = 'E'; /* restrict this directive to elements */
        directive.template = "My first directive: {{textToInsert}}";
    
        return directive;
    });
    

    In case that HTML template grows big, it is gets hard to write and maintain the HTML inside a JavaScript string. You can then put the HTML into its own file and have AngularJS load it from that file. You do so by putting the URL of the HTML template file into the templateUrl property of the directive definition object. Here is an example:

    myapp = angular.module("myapp", []);
    
    myapp.directive('div', function() {
        var directive = {};
    
        directive.restrict = 'E'; /* restrict this directive to elements */
        directive.templateUrl = "/myapp/html-templates/div-template.html";
    
        return directive;
    });
    

    AngularJS will now load the HTML template from the URL set in the templateUrl property.

    Using the separate HTML template file and the templateUrl property is especially useful when you create more specialized directives, like a directives showing user info. Here is an example:

    myapp = angular.module("myapp", []);
    
    myapp.directive('userinfo', function() {
        var directive = {};
    
        directive.restrict = 'E'; /* restrict this directive to elements */
        directive.templateUrl = "/myapp/html-templates/userinfo-template.html";
    
        return directive;
    });
    

    This example creates a directive that is activated whenever AngularJS finds a <userinfo> element. AngularJS loads the HTML template found at /myapp/html-templates/userinfo-template.html, and interprets that as if it had been located inside the parent HTML file from the beginning.

    Isolating the $scope From the Directive

    In the example above the userinfo directive was bound hard to the $scope variable because the HTML template referenced the textToInsert property directly. Referencing $scope variables directly makes it hard to reuse the directive more than once within the same controller, since the $scope variables typically have the same values everywhere inside the same controller. For instance, if you wanted to have this HTML in your page:

    <userinfo></userinfo>
    <userinfo></userinfo>
    

    Then the two <userinfo> elements would be replaced by the same HTML template, which is bound to the same $scope variable. The result would be that the two <userinfo> elements would be replaced by the exact same HTML code.

    To be able to bind the two <userinfo> elements to different values in the $scope object, you need to bind the HTML template to an isolate scope.

    An isolate scope is a separate scope object tied to the directive. Here is how you define it in the directive definition object:

    myapp.directive('userinfo', function() {
        var directive = {};
    
        directive.restrict = 'E';
    
        directive.template = "User : {{user.firstName}} {{user.lastName}}";
    
        directive.scope = {
            user : "=user"
        }
    
        return directive;
    })
    

    Notice how the HTML template has two interpolation directives bound to {{user.firstName}} and {{user.lastName}}. Notice the user. part. And notice the directive.scope property. The directive.scope property is a JavaScript object which contains a property named user. The directive.scope property is the isolate scope object, and the HTML template is now bound to the directive.scope.user object (via the {{user.firstName}} and {{user.lastName}} interpolation directives).

    The directive.scope.user property is set to "=user". That means, that the directive.scope.user property is bound to the property in the scope property (not in the isolate scope) with the name passed to the user attribute of the <userinfo> element. It sounds confusing, so look at this HTML example:

    <userinfo user="jakob"></userinfo>
    <userinfo user="john"></userinfo>
    

    These two <userinfo> element contain a user attribute. The value of these attributes contain the names of properties in the $scope object which are to be referenced by the isolate scope object's userinfo property.

    Here is a full example:

    <userinfo user="jakob"></userinfo>
    <userinfo user="john"></userinfo>
    
    <script>
    myapp.directive('userinfo', function() {
        var directive = {};
    
        directive.restrict = 'E';
    
        directive.template = "User : <b>{{user.firstName}}</b> <b>{{user.lastName}}</b>";
    
        directive.scope = {
            user : "=user"
        }
    
        return directive;
    });
    
    myapp.controller("MyController", function($scope, $http) {
        $scope.jakob = {};
        $scope.jakob.firstName = "Jakob";
        $scope.jakob.lastName  = "aitechtonic";
    
        $scope.john = {};
        $scope.john.firstName = "John";
        $scope.john.lastName  = "Doe";
    });
    
    </script>
    

    The compile() and link() Functions

    If you need to do something more advanced inside your directive, something that you cannot do with an HTML template, you can use the compile() and link() functions instead.

    The compile() and link() functions define how the directive is to modify the HTML that matched the directive.

    The compile() function is called once for each occurrence of the directive in the HTML page. The compile() function can then do any one-time configuration needed of the element containing the directive.

    The compile() function finishes by returning the link() function. The link() function is called every time the element is to be bound to data in the $scope object.

    As mentioned, you add the compile() function to the directive definition object, and the compile() function has to return the link() function when executed. Here is how that looks:

    <script>
    myapp = angular.module("myapp", []);
    myapp.directive('userinfo', function() {
        var directive = {};
    
        directive.restrict = 'E'; /* restrict this directive to elements */
    
    
        directive.compile = function(element, attributes) {
            // do one-time configuration of element.
    
            var linkFunction = function($scope, element, atttributes) {
                // bind element to data in $scope
            }
    
            return linkFunction;
        }
    
        return directive;
    });    
    </script>    
    

    The compile() function takes two parameters: The element and attributes parameters.

    The element parameter is a jqLite wrapped DOM element. AngularJS contains a lite version of jQuery to help you do DOM manipulation, so the element's DOM manipulation methods are the same as you know from jQuery.

    The attributes parameter is a JavaScript object containing properties for all the attributes of the DOM element. Thus, to access an attribute named type you would write attributes.type.

    The link() function takes three parameters: The $scope parameter, the element parameter and the attributes parameter. The element and attributes parameter is the same as passed to the compile() function. The $scope parameter is the normal scope object, or an isolate scope in case you have specified one in the directive definition object.

    The compile() and link() function names are actually confusing. They are inspired by compiler terms. I can see the resemblance, but a compiler parses an input once, and creates an output. A directive configures an HTML element and then updates that HTML subsequently whenever the $scope object changes.

    A better name for the compile() function would have been something like create(), init() or configure(). Something that signals that this function is only called once.

    A better name for the link() function would have been something like bind() or render(), which signals that this function is called whenever the directive needs to bind data to it, or to re-render it.

    Here is a full example that shows a directive that uses both a compile() and link() function:

    <div ng-controller="MyController" >
        <userinfo >This will be replaced</userinfo>
    </div>
    
    <script>
        myapp = angular.module("myapp", []);
        myapp.directive('userinfo', function() {
            var directive = {};
    
            directive.restrict = 'E'; /* restrict this directive to elements */
    
            directive.compile = function(element, attributes) {
                element.css("border", "1px solid #cccccc");
    
                var linkFunction = function($scope, element, attributes) {
                    element.html("This is the new content: " + $scope.firstName);
                    element.css("background-color", "#ffff00");
                }
    
                return linkFunction;
            }
    
            return directive;
        })
        myapp.controller("MyController", function($scope, $http) {
            $scope.cssClass = "notificationDiv";
    
            $scope.firstName = "Jakob";
    
            $scope.doClick = function() {
                console.log("doClick() called");
            }
        });
    </script>    
    

    The compile() function sets a border on the HTML element. This is only executed once because the compile() function is only executed once.

    The link() function replaces the content of the HTML element, and sets the background color to yellow.

    There is no particular reason why the border was set in the compile() function, and the background color in the link() function. Both could have been set in the compile() function, or both in the link() function. If set in the compile() function they would only have been set once (which is often what you want). If set in the link() function they would be set every time the HTML element is bound to data in the $scope object. This might be useful if you needed to set the border and background color differently depending on data in the $scope object.

    Setting Only a link() Function

    Sometimes you do not need the compile() step for your directive. You only need th link() function. In that case you can set the link() function directly on the directive definition object. Here is the example from before, with only a link function:

    <div ng-controller="MyController" >
        <userinfo >This will be replaced</userinfo>
    </div>
    
    <script>
        myapp = angular.module("myapp", []);
        myapp.directive('userinfo', function() {
            var directive = {};
    
            directive.restrict = 'E'; /* restrict this directive to elements */
    
            directive.link = function($scope, element, attributes) {
                    element.html("This is the new content: " + $scope.firstName);
                    element.css("background-color", "#ffff00");
            }
    
            return directive;
        })
        myapp.controller("MyController", function($scope, $http) {
            $scope.cssClass = "notificationDiv";
    
            $scope.firstName = "Jakob";
    
            $scope.doClick = function() {
                console.log("doClick() called");
            }
        });
    </script>
    

    Notice how the link() function does the same as the link() function returned in the previous example.

    Directives Which Wraps Elements Via Transclusion

    The examples we have seen so far all set the content of the element matching the directive themselves, either via JavaScript code or an HTML template. But what if you wanted a directive to wrap elements inserted into the directive body by the developer? For instance:

    <mytransclude>This is a transcluded directive {{firstName}}</mytransclude>
    

    The directive is marked by the <mytransclude> element. But the content inside it is set by the developer. Thus, this part of the HTML should not be replaced by the directive's HTML template. We actually want that part of the HTML to be processed by AngularJS. This processing is called "transclusion".

    In order to make AngularJS process the HTML inside a directive, you have to set the transclude property of the directive definition object to true. You will also have to tell AngularJS what part of the directive's HTML template that is to contain the transcluded HTML. You do so by inserting the ng-transclude attribute (a directive, really) into the HTML element in the HTML template where you want the transcluded HTML inserted.

    Here is an AngularJS directive that shows how to use transclusion:

    <mytransclude>This is a transcluded directive {{firstName}}</mytransclude>
    
    <script>
        myapp = angular.module("myapp", []);
        myapp.directive('mytransclude', function() {
            var directive = {};
    
            directive.restrict = 'E'; /* restrict this directive to elements */
            directive.transclude = true;
            directive.template = "<div class='myTransclude' ng-transclude></div>";
    
            return directive;
        });
        myapp.controller("MyController", function($scope, $http) {
            $scope.firstName = "Jakob";
        });
    </script>
    

    Notice the HTML inside the <mytransclude> element. This HTML code contains the interpolation directive {{firstName}}. We want AngularJS to process this HTML for us so that interpolation directive is executed. To achieve that I have set the transclude property to true on the directive definition object. I have also inserted an ng-transclude attribute into the HTML template. This attribute tells AngularJS what element to insert the transcluded HTML into.

  • ANGULARJS MODULARIZATION & DEPENDENCY INJECTION ↓

    AngularJS comes with a built-in dependency injection mechanism. You can divide your application into multiple different types of components which AngularJS can inject into each other. Modularizing your application makes it easier to reuse, configure and test the components in your application.

    AngularJS contains the following core types of objects and components:

    • Value
    • Factory
    • Service
    • Provider
    • Constant

    These core types can be injected into each other using AngularJS dependency injection mechanism. Throughout the rest of this text I will explain how to define and inject these components into each other.

    Value

    A value in AngularJS is a simple object. It can be a number, string or JavaScript object. Values are typically used as configuration which is injected into factories, services or controllers.

    A value has to belong to an AngularJS module. Here are three examples that add values to an AngularJS module:

    var myModule = angular.module("myModule", []);
    
    myModule.value("numberValue", 999);
    
    myModule.value("stringValue", "abc");
    
    myModule.value("objectValue", { val1 : 123, val2 : "abc"} );
    

    The values are defined using the value() function on the module. The first parameter is the name of the value, and the second parameter is the value itself. Factories, services and controllers can now reference these values by their name.

    Injecting a Value

    Injecting a value into an AngularJS controller function is done simply by adding a parameter with the same name as the value (the first parameter passed to the value() function when the value is defined). Here is an example:

    var myModule = angular.module("myModule", []);
    
    myModule.value("numberValue", 999);
    
    myModule.controller("MyController", function($scope, numberValue) {
    
        console.log(numberValue);
    
    });
    

    Notice how the second parameter of the controller function has the same name as the value.

    Factory

    Factory is a function that creates values. When a service, controller etc. needs a value injected from a factory, the factory creates the value on demand. Once created, the value is reused for all services, controllers etc. which need it injected. Thus, a factory differs from a value in that it can use a factory function to create the object it returns. You can also inject values into a factory for use when creating the object. You cannot do that with a value.

    Here is an example that defines a factory on a module, and a controller which gets the factory created value injected:

    var myModule = angular.module("myModule", []);
    
    myModule.factory("myFactory", function() {
        return "a value";
    });
    
    
    myModule.controller("MyController", function($scope, myFactory) {
    
        console.log(myFactory);
    
    });
    

    As you can see, it is very similar to defining and injecting a value object. Keep in mind that it is not the factory function that is injected, but the value produced by the factory function.

    Injecting Values Into a Factory

    You can inject a value into a factory. It works just like when a value is injected into a controller. Here is an example:

    var myModule = angular.module("myModule", []);
    
    myModule.value("numberValue", 999);
    
    myModule.factory("myFactory", function(numberValue) {
        return "a value: " + numberValue;
    });
    

    In this example the injected value is used to create the object created by the factory function.

    Service

    A service in AngularJS is a singleton JavaScript object which contains a set of functions. The functions contain whatever logic is necessary for the service to carry out its work.

    AngularJS services are created using the service() function on a module. Here is an example:

    function MyService() {
        this.doIt = function() {
            console.log("done");
        }
    }
    
    
    var myModule = angular.module("myModule", []);
    
    myModule.service("myService", MyService);
    

    As you can see, services are defined somewhat differently than factories and values. First of all, the service is defined as a separate, named function. That is because services in AngularJS are created using the new keyword. Thus, AngularJS will do this internally:

    var theService = new MyService();
    

    Apart from defining services as functions with functions inside, you add them to and use them with AngularJS just like you would with a value or function. You inject a service into a controller like this:

    function MyService() {
        this.doIt = function() {
            console.log("done");
        }
    }
    
    
    var myModule = angular.module("myModule", []);
    
    myModule.service("myService", MyService);
    
    
    myModule.controller("MyController", function($scope, myService) {
    
        myService.doIt();
    
    });
    

    Injecting Values Into a Service

    You can inject values into a service, just like you can inject values into controllers, or services into controllers etc. Here is an example:

    var myModule = angular.module("myModule", []);
    
    myModule.value  ("myValue"  , "12345");
    
    function MyService(myValue) {
        this.doIt = function() {
            console.log("done: " + myValue;
        }
    }
    
    myModule.service("myService", MyService);
    

    Notice how the parameter to the MyService function is named the same as the value registered on the module. Thus, the value will be injected into the service when it is created.

    Providers

    Providers in AngularJS is the most flexible form of factory you can create. You register a provider with a module just like you do with a service or factory, except you use the provider() function instead. Here is an AngularJS provider example:

    var myModule = angular.module("myModule", []);
    
    myModule.provider("mySecondService", function() {
        var provider = {};
    
        provider.$get = function() {
            var service = {};
    
            service.doService = function() {
                console.log("mySecondService: Service Done!");
            }
    
            return service;
        }
    
        return provider;
    });
    

    As you can see, the provider() function takes 2 parameters. The first parameter is the name of the service / object which the provider creates. In this case the name is mySecondService. The second parameter is the function which creates the provider. Note: The provider is itself a factory, so at this time no actual service or object is created from the provider. Only the function creating the provider is defined.

    When you look at the function creating the provider you can see that the provider is a JavaScript object.

    The JavaScript provider object contains a single $get() function. This is the factory function of the provider. In other words, the $get() function creates whatever the provider creates (service, value etc.). In the example above, the provider creates a service object which contains a single service function (standard JavaScript function) called doService().

    In order to get the product of a provider injected into a controller, do specify a dependency on the provider, just like you would with a service. What is injected into the controller is the product created by the provider, not the provider itself. Here is an AngularJS provider injection example:

    myModule.controller("MyController", function($scope, mySecondService) {
    
        $scope.whenButtonClicked = function() {
            mySecondService.doIt();
        }
    
    });
    

    As you can see, the name of the provider is used as a parameter in the controller function. The object created by the provider's $get() function will be injected into this parameter.

    Configuring a Provider

    It is possible to configure a provider further via calls to its function during the configuration phase of a module. Here is an example:

    var myModule = angular.module("myModule", []);
    
    myModule.provider("mySecondService", function() {
        var provider = {};
        var config   = { configParam : "default" };
    
        provider.doConfig = function(configParam) {
            config.configParam = configParam;
        }
    
        provider.$get = function() {
            var service = {};
    
            service.doService = function() {
                console.log("mySecondService: " + config.configParam);
            }
    
            return service;
        }
    
        return provider;
    });
    
    myModule.config( function( mySecondServiceProvider ) {
        mySecondServiceProvider.doConfig("new config param");
    });
    
    myModule.controller("MyController", function($scope, mySecondService) {
    
        $scope.whenButtonClicked = function() {
            mySecondService.doIt();
        }
    
    });
    
    

    Notice how the provider object now has an extra function called doConfig(). This function can be used to set a configuration parameter on the provider.

    Notice also the call to the myModule.config() function. The config function takes a function as parameter. This function can configure the module. The function passed to config() takes a single parameter named mySecondServiceProvider. That is the same name the provider is registered with plus Provider as suffix. The suffix tells AngularJS to inject the provider itself, and not the object created by the provider. Inside the function passed to the config() function the mySecondServiceProvider.doConfig() function is called, which sets the config parameter on the provider.

    The controller defined later in the example just depends on the object created by the provider (not the provider itself). It does so by taking a parameter named mySecondService which is the name the provider of the service is registered with. As you can see, the service used from inside the $scope.whenButtonClicked() function.

    Constants

    In the previous section on providers you saw how to configure a provider via the module.config() function. Unfortunately you cannot inject values into the module.config() function. Instead you can inject constants.

    Constants in AngularJS are defined using the module.constants() function. Here is an AngularJS constant example:

    myModule.constant("configValue", "constant config value");
    

    This constant can now be injected into the module.config() function like this:

    myservices.config( function( mySecondServiceProvider, configValue ) {
        mySecondServiceProvider.doConfig(configValue);
    });
    

    As you can see, the parameter configValue matches the name of the constant which is also configValue. Thus the value of the constant will be injected into this parameter. The constant value is then passed as parameter to the doConfig() function on the mySecondServiceProvider provider.

    Dependencies Between Modules

    As you have seen, values, factories and services are added to an AngularJS module. It is possible for one module to use the values, factories and services of another module. In order to do so, a module needs to declare a dependency on the module which contains the values, factories and services it wants to use. Here is an example:

    var myUtilModule = angular.module("myUtilModule", []);
    
    myUtilModule.value  ("myValue"  , "12345");
    
    
    var myOtherModule = angular.module("myOtherModule", ['myUtilModule']);
    
    myOtherModule.controller("MyController", function($scope, myValue) {
    
    });
    

    Notice how the second module (myOtherModule) lists the name of the first module (myUtilModule) in the second parameter (inside the array) passed to the angular.module() function. This tells AngularJS that all values, factories and services defined inside the myUtilModule should be available inside the myOtherModule module too. In other words, myOtherModule depends on myUtilModule.

    Second, notice how the MyController controller function now declares a parameter named myValue. This value will be provided from the value registered on the myUtilModule module.

    Minification Safe Dependency Injection in AngularJS

    When you minify JavaScript the JavaScript minifier replaces the names of local variables and parameters with shorter names. However, AngularJS uses the parameter names of controller functions, factories, services and providers to decide what to inject into their factory functions. If the names are changed, AngularJS cannot inject the correct objects.

    To make your AngularJS code minification safe, you need to provide the names of the objects to inject as strings. You wrap these strings in an array together with the function that needs the values injected. Here is an AngularJS minification safe dependency injection example:

    var myapp = angular.module("myapp", ['myservices']);
    
    myapp.controller("AController", ['$scope', function(p1) {
        p1.myvar = "the value";
    }]);
    

    This example injects the $scope object into the p1 parameter of the controller function.

    Notice how the controller function is registered. Instead of passing the controller function to the angular.controller function directly, an array is passed instead. This array contains the name of the value to inject into the controller function, as well as the controller function itself. The controller function is always the last value in this array. If you need to inject more than one value, the value names are listed in the beginning of the array and in the sequence they are to be injected into the function. Here is a minification safe multi value example:

    var myapp = angular.module("myapp", ['myservices']);
    
    myapp.controller("AController", ['$scope', '$http', function(p1, p2) {
        p1.myvar = "the value";
        p2.get("/myservice.json");
    }]);
    

    This example injects the $scope object into the p1 parameter, and the $http service into the p2 parameter of the controller function.

    Now it no longer matters what the parameter names of the controller function are. AngularJS will use the strings in the beginning of the array to determine what to inject into the controller function.

    The same mechanism can be used for factories, services and providers to provide minification safe dependency injection. Here is a minification safe factory, service and provider example:

    var myutil = angular.module("myutil", []);
    
    
    myutil.value("safeValue", "a safe value");
    
    
    myutil.factory("safeFactory", ['safeValue', function(p1) {
        return { value : p1 };
    }]);
    
    
    function MySafeService(p1){
        this.doIt = function() {
            return "MySafeService.doIt() called: " + p1.value;
        }
    }
    myutil.service("safeService", ['safeFactory', MySafeService]);
    
    
    myutil.provider("safeService2", function() {
        var provider = {};
    
        provider.$get = ['safeService', function(p1) {
            var service = {};
    
            service.doService = function() {
                console.log("safeService from provider: " + p1.doIt());
            }
    
            return service;
        }];
    
        return provider;
    });
    
    myapp.controller("AController", ['$scope', 'safeService2', function(p1, p2) {
        p1.myvar = "the value";
        p2.doService();
    }]);
    

    Notice especially the declaration of the provider. Notice how the dependencies are not specified on the provider factory function, but on the $get() function of the provider returned from inside the provider factory function. Actually, an array with names of dependencies and the function implementation is used instead of just a $get() function. Other than that, specifying dependencies works the same for providers as for factories, services and controller functions.

  • ANGULARJS ROUTES ↓

    AngularJS routes enable you to create different URLs for different content in your application. Having different URLs for different content enables the user to bookmark URLs to specific content, and send those URLs to friends etc. In AngularJS each such bookmarkable URL is called a route.

    AngularJS routes enables you to show different content depending on what route is chosen. A route is specified in the URL after the # sign. Thus, the following URL's all point to the same AngularJS application, but each point to different routes:

        http://myangularjsapp.com/index.html#books
        http://myangularjsapp.com/index.html#albums
        http://myangularjsapp.com/index.html#games
        http://myangularjsapp.com/index.html#apps
    

    When the browser loads these links, the same AngularJS application will be loaded (located at http://myangularjsapp.com/index.html), but AngularJS will look at the route (the part of the URL after the #) and decide what HTML template to show.

    At this point it may sound a little abstract, so let us look at a fully working AngularJS route example:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>AngularJS Routes example</title>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular-route.min.js"></script>
    </head>
    
    <body ng-app="sampleApp">
    
    <a href="#/route1">Route 1</a><br/>
    <a href="#/route2">Route 2</a><br/>
    
    
    <div ng-view></div>
    
    <script>
        var module = angular.module("sampleApp", ['ngRoute']);
    
        module.config(['$routeProvider',
            function($routeProvider) {
                $routeProvider.
                    when('/route1', {
                        templateUrl: 'angular-route-template-1.jsp',
                        controller: 'RouteController'
                    }).
                    when('/route2', {
                        templateUrl: 'angular-route-template-2.jsp',
                        controller: 'RouteController'
                    }).
                    otherwise({
                        redirectTo: '/'
                    });
            }]);
    
        module.controller("RouteController", function($scope) {
    
        })
    </script>
    

    Each part of this sample application will be explained in the following sections.

    Including the AngularJS Route Module

    The first thing to notice in the example application above is the extra JavaScript included inside the head section:

    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular-route.min.js"></script>
    

    The AngularJS Route module is contained in its own JavaScript file. To use it we must include in our AngularJS application.

    Declaring a Dependency on the AngularJS Route Module

    The second thing to notice is that the applications's AngularJS module (called sampleApp) declares a dependency on the AngularJS route module:

    var module = angular.module("sampleApp", ['ngRoute']);
    

    The application's module needs to declare this dependency in order to use the ngRoute module. This is explained in more detail in my modularization and dependency injection tutorial, in the section about dependencies-between-modules.

    The ngView Directive

    The third thing to notice in the example above is the use of the ngView directive:

    <div ng-view></div>
    

    Inside the div with the ngView directive (can also be written ng-view) the HTML template specific to the given route will be displayed.

    Configuring the $routeProvider

    The fourth thing to notice in the example shown at the beginning of this text is the configuration of the $routeProvider. The $routeProvider is what creates the $route service. By configuring the $routeProvider before the $route service is created we can set what routes should result in what HTML templates being displayed.

    Here is the code from the example:

    <script>
        module.config(['$routeProvider',
            function($routeProvider) {
                $routeProvider.
                    when('/route1', {
                        templateUrl: 'angular-route-template-1.jsp',
                        controller: 'RouteController'
                    }).
                    when('/route2', {
                        templateUrl: 'angular-route-template-2.jsp',
                        controller: 'RouteController'
                    }).
                    otherwise({
                        redirectTo: '/'
                    });
            }]);
    </script>
    

    The $routeProvider is configured in the module's config() function. We pass a configuration function to the module's config() function which takes the $routeProvider as parameter. Inside this function we can now configure the $routeProvider.

    The $routeProvider is configured via calls to the when() and otherwise() functions.

    The when() function takes a route path and a JavaScript object as parameters.

    The route path is matched against the part of the URL after the # when the application is loaded. As you can see, the two route paths passed to the two when() function calls match the two route paths in the href attribute of the links in the same example.

    The JavaScript object contains two properties named templateUrl and controller. The templateUrl property tells which HTML template AngularJS should load and display inside the div with the ngView directive. The controller property tells which of your controller functions that should be used with the HTML template.

    The otherwise() function takes a JavaScript object. This JavaScript object tells AngularJS what it should do if no route paths matches the given URL. In the example above the browser is redirected to the same URL with #/ as route path.

    Links to Routes

    The final thing to notice in this example is the two links in the HTML page:

    <a href="#/route1">Route 1</a><br/>
    <a href="#/route2">Route 2</a><br/>
    

    Notice how the part of the URLs after the # matches the routes configured on the $routeProvider.

    When one of these links is clicked, the URL in the browser window changes, and the div with the ngView directive will show the HTML template matching the route path.

    Route Parameters

    You can embed parameters into the route path. Here is an AngularJS route path parameter example:

    #/books/12345
    

    This is a URL with a route path in. In fact it pretty much consists of just the route path. The parameter part is the 12345 which is the specific id of the book the URL points to.

    AngularJS can extract values from the route path if we define parameters in the route paths when we configure the $routeProvider. Here is the example $routeProvider from earlier, but with parameters inserted into the route paths:

    <script>
        module.config(['$routeProvider',
            function($routeProvider) {
                $routeProvider.
                    when('/route1/:param', {
                        templateUrl: 'angular-route-template-1.jsp',
                        controller: 'RouteController'
                    }).
                    when('/route2/:param', {
                        templateUrl: 'angular-route-template-2.jsp',
                        controller: 'RouteController'
                    }).
                    otherwise({
                        redirectTo: '/'
                    });
            }]);
    </script>
    

    Both of the URLs in the when() calls now define a parameter. It is the part starting from the colon (:param)

    AngularJS will now extract from the URL (route path) whatever comes after the #/route1/ part. Thus, from this URL:

    #/route1/12345
    

    The value 12345 will be extracted as parameter.

    Your controller functions can get access to route parameters via the AngularJS $routeParams service like this:

    module.controller("RouteController", function($scope, $routeParams) {
        $scope.param = $routeParams.param;
    })
    

    Notice how the controller function takes the $routeParams service as parameter, and then copies the parameter named param into the $scope.param property. Now your AngularJS views can get access to it, or you can use it in AJAX calls etc.

    Here is a full AngularJS route parameter example:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>AngularJS Routes example</title>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular-route.min.js"></script>
    </head>
    
    <body ng-app="sampleApp">
    
    <a href="#/route1/abcd">Route 1 + param</a><br/>
    <a href="#/route2/1234">Route 2 + param</a><br/>
    
    
    <div ng-view></div>
    
    <script>
        var module = angular.module("sampleApp", ['ngRoute']);
    
        module.config(['$routeProvider',
            function($routeProvider) {
                $routeProvider.
                        when('/route1/:param', {
                            templateUrl: 'angular-route-template-1.jsp',
                            controller: 'RouteController'
                        }).
                        when('/route2/:param', {
                            templateUrl: 'angular-route-template-2.jsp',
                            controller: 'RouteController'
                        }).
                        otherwise({
                            redirectTo: '/'
                        });
            }]);
    
        module.controller("RouteController", function($scope, $routeParams) {
            $scope.param = $routeParams.param;
        })
    </script>
    
    
    
    </body>
    </html>    
    
  • ANGULARJS INTERNATIONALIZATION ↓

    AngularJS has built-in support for internationalization of numbers and dates. In this text I will take a look at how they work.

    Internationalization in Filters

    Some of the built-in AngularJS filters supports internationalization. For instance, the date and currency filters have built-in support for internationalization. Here is how you would normally use these filters:

    {{ theDate  | date: 'fullDate' }}
    {{ theValue | currency }}
    {{ theValue | number }}
    

    The date filter will format the variable theDate as a date according to the locale chosen in the web app. The same is true for the currency and number filter.

    Filters are covered in more detail in the section about filtering in my views and directives tutorial: AngularJS Filtering.

    The Date Filter

    The date filter accepts the following values specifying how to format the date:

    • short
    • medium
    • fullDate
    • shortDate
    • mediumDate
    • longDate
    • shortTime
    • mediumTime

    Here are a few date filter examples:

     {{ theDate  | date: 'shortDate' }}
     {{ theDate  | date: 'longDate'  }}
    

    The Currency Filter

    The currency filter will use the currency symbol associated with the chosen locale when formatting a number as a currency. If you need to use a different currency symbol, for instance if the users wants to see a price in a different currency, you can specify the currency symbol to the currency filter like this:

    {{ theValue | currency : '$' }}
    {{ theValue | currency : '£' }}
    {{ theValue | currency : '€' }}
    

    Notice how the last two examples use the HTML entities for pounds and euros.

    The Number Filter

    The number filter formats numbers according to the chosen locale. For instance, in English the thousand separator is . and the decimal separator is , whereas in Danish it is the opposite. Here is a number filter example:

    {{ theValue | number }}
    

    Setting the Locale

    To tell AngularJS what locale (language and country) to use when writing localized output, you need to include the corresponding AngularJS locale file. Here is an example that includes the Danish locale:

    <script src="https://code.angularjs.org/1.2.5/i18n/angular-locale_da-dk.js"></script>
    

    Include this after including the AngularJS main JavaScript file, and it should work out of the box. There nothing more that needs to be done than including this file.

    To find the correct locale for your country, look at code.angularjs.org, click on the version of AngularJS you are using, and then click on the i18n directory. In that directory you see a list of all the available locales. Find the one that matches the country or contries you want to support, and then download them and include them in your HTML page (or reference them directly at code.angularjs.org).

    Full AngularJS Internationalization Example

    Here is a full AngularJS internationalization example:

    <!DOCTYPE html>
    <html lang="en">
    <head>
        <title>AngularJS Routes example</title>
        <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.5/angular.min.js"></script>
        <script src="https://code.angularjs.org/1.2.5/i18n/angular-locale_da-dk.js"></script>
    </head>
    
    
    <body ng-app="myapp">
    
    AngularJS I18n
    
    <div ng-controller="mycontroller">
        {{theDate  | date : "fullDate"}} <br/>
        {{theValue | currency }}
    </div>
    
    
    
    <script>
        var module  = angular.module("myapp", []);
    
        module.controller("mycontroller", function($scope) {
    
            $scope.theDate  = new Date();
            $scope.theValue = 123.45;
    
        });
    </script>
    
    </body>
    </html>
    

    It is this line which includes the language (locale) JavaScript file:

    <script src="https://code.angularjs.org/1.2.5/i18n/angular-locale_da-dk.js"></script>
    
  • ANGULARJS CRITIQUE ↓

    Over the years I have looked at Java Swing, SWT, Flex, GWT, jQuery, SmartClient, JSP, Wicket, Struts, Spring MVC and now AngularJS, in my long search for the "perfect" GUI toolkit for web apps. I hoped AngularJS would be the end of my search, but right from the beginning something in AngularJS smelled wrong to me. It took me some time before I was able to put my finger on just what it is I don't like.

    Don't get me wrong. You can make web apps just fine with AngularJS. There are just some aspects I don't like - choices I don't agree with. These are:

    1. The AngularJS directives are a suboptimal choice for HTML generation.
    2. The 2-way data binding is not always that useful.

    Each of these aspects are discussed below.

    AngularJS Directives And The Declarative / Imperative Paradigm Mismatch

    My main point of critique is against the AngularJS HTML templating style including AngularJS directives. These are a core part of AngularJS so you cannot really choose not to use them.

    AngularJS uses the popular {{ }} HTML templating style also found in frameworks like Knockout and Handlebars. Here is an example:

    <ol>
       <li ng-repeat="theItem in myData.getItems()">{{theItem.text}}</li>
    </ol>
    

    While this style works just fine for the simple cases, it works less well for more advanced cases.

    In web apps the code has to insert data into the HTML page somehow. You can generate the whole HTML page using an imperative language, like Java (on the server) or JavaScript (in the browser). Or, you can try to "teach HTML new tricks" so HTML becomes able to do some of the things you can do in an imperative language. Or, you find a middle ground in which the more static parts of the HTML page is defined using HTML syntax, and the more advanced parts are created using a imperative language. HTML is a declarative language, so another way to put it is, that either you mix a bit of the imperative into the declarative, or a bit of the declarative into the imperative. I will get back to this again later.

    In my opinion generating HTML on the client cases works better than generating HTML on the server in most cases. It results in cleaner HTML generation code, and cleaner backend code too. This means, that the imperative language should run in the browser. In AngularJS that language is JavaScript and that is just fine.

    Using declarative HTML templates with a bit of data binding injected is not a new idea. It has been tried before in JSP (JavaServer Pages). Here is an example:

    <span><%=myObject.getMyProperty()%></span>
    

    In AngularJS it would look like this:

    <span>{{myObject.getMyProperty()}}</span>
    

    This data binding injection style is incredibly simple for the simple cases, and thus immediately appeals to most developers. However, as soon as your web app gets more advanced you realize that you need some kind of imperative control logic to direct the HTML generation. Two imperative constructs you will soon need is looping and branching (if-statements). Here is how looping looks in JSP in the first versions:

    <%
        for(int i=0; i < list.size(); i++) {
           MyObject myObject = (MyObject) list.get(i);
    %>
           <span><%=myObject.getMyProperty()%></span>
    <% }  %>
    

    Notice how the <% %> markers switches between Java and HTML. While this allowed imperative control logic to be mixed with the declarative HTML, developers soon realized that mixing Java directly into the HTML resulted in really messy code when the HTML pages got more advanced. The syntaxes of Java and HTML just didn't complement each other very well.

    To solve that problem the JSP standard added a concept called "Tag Libraries". Tag libraries used an XML syntax to allow imperative control to be mixed with the HTML. Early frameworks like Struts utilized this to create tag libraries for data binding, iteration, branches etc. Here is an early iteration example:

     <logic:iterate id="theBean" name="beans">
         <span><bean:write name="theBean" property="theProperty"/></span>
     </logic:iterate>
    

    This way the syntax of the imperative control logic complements HTML better. However, you run into other problems instead. First, it is not so easy to express advanced constructs like recursive iteration of tree or graph data structures. Second, your HTML template gets messy when you insert too much imperative logic into it. Third, the XML syntax does not support imperative control structures so well. Expressing them in XML is more clumsy and verbose than using a syntax specifically designed for that purpose.

    It did not end so well for JSP. The Java community learned that there were better approaches. First were called "Model 2" (early Struts and Spring MVC), and later "Component Oriented Frameworks" (Wicket and JSF - JavaServer Faces). The last time I checked I could not even find JSP in Oracle' official Java Enterprise Edition tutorial.

    It is easy to ascribe the demise of JSP to the fact that it was generating HTML on the server. However, that is only part of the problems with JSP.

    The Declarative / Imperative Paradigm Mismatch

    Declarative languages (such as HTML and XML) are good a modeling state such as documents, or the overall composition of a GUI. Imperative languages (such as JavaScript, Java, C etc.) are good a modeling operations. The syntaxes of both declarative and imperative languages were designed to support their specific purposes. Therefore, when you try to use a declarative language to mimic imperative mechanisms it may work for simple cases, but as the cases get more advanced the code tend to become clumsy. The syntax just wasn't intended for that purpose. Granted, you can create all kinds of workarounds to make it look nicer, but that doesn't change the underlying fact, that you are trying to use a declarative language for imperative operations.

    The same is true the other way around. Using an imperative language will often also get clumsy. Anyone who has tried writing an HTML document using JavaScript's document.write() function, or wired up a Java Swing GUI using Java, or an SWT GUI for that matter, knows how clumsy this code can get.

    When you try to use a declarative language for imperative purposes, or an imperative language to for declarative purposes, you end up with what I call "The declarative / imperative paradigm mismatch". This mismatch often results in clumsy or ugly code.

    It is easy to think that the declarative / imperative mismatch can be avoided with a programming language that is designed to handle both paradigms. But the problem goes deeper than the language syntax.

    It is not the syntax of a programming language that decides if the language is declarative or imperative. It is the semantic meaning of what the language describes that decides between declarative and imperative. You could invent a more Java-like syntax to describe HTML elements. Or a more HTML-like syntax to describe Java instructions. But such syntaxes would not change the fact that one language describes state (HTML documents) and the other language describe commands (operations). Thus, a Java-like syntax for describing HTML documents would still be declarative, and a more HTML-like syntax for describing Java-operations would still be imperative.

    Think about it for just a moment. JavaScript actually already has a declarative mechanism built in for defining JavaScript objects. It's JSON - JavaScript Object Notation. You could actually mimic HTML using JSON. Here is an example:

    {
      html : {
        head : { title : "JSON mimicking HTML" },
        body : {
          text : "Hello World"
        }
      }
    }
    

    Of course this doesn't mimic HTML attributes or even the combination of text and HTML elmeents possible in the body of an HTML element. But I am sure the JSON syntax could have been extended to cover that.

    Imagine you had to generate a JSON object using JavaScript - by mixing JavaScript instructions in-between the JSON notation. Regardless of the JavaScript-like syntax, it would be a hard problem to solve elegantly.

    Now we are down to what the declarative / imperative paradigm mismatch is really about. It's just hard to design one language that can both describe state and support dynamic generation of state intertwined, regardless of the syntax. JSP is a good example of that. The above JavaScript / JSON example is a good example of that.

    XSL is another fine example of the the declarative / imperative mismatch. XSL attempted to be a declarative language for describing XML document transformations. Again, it worked beautifully for simple transformations, but once you got to more advanced cases, XSL broke own. You had to resort to an imperative language for those parts.

    AngularJS is using a similar approach with its directives. AngularJS directives are either HTML elements, attributes, CSS classes or HTML comments which trigger imperative actions in their respective JavaScript implementations. AngularJS directives are similar to JSP tag libraries and are thus prone to the same problems. I find it puzzling that some developers (in the Java community at least) wrinkle their noses at JSP but praise AngularJS. Despite the amount of rational thinking our jobs require, the IT industry is far from always behaving rationally - but that is another topic for another article.

    Finding the Declarative / Imperative Balance

    There are definitely parts of a GUI which it makes sense to define using a markup language. Markup languages are typically declarative, and declarative languages are good at modeling state. The composition of a GUI is state. Thus, it makes sense to model the overall composition of a GUI using a declarative language (e.g. HTML).

    But there are also parts of a GUI (e.g. advanced GUI components) that have too complex a behaviour to be sensibly defined using a declarative language like HTML. For instance, an advanced data grid, or a tree view, or interactive graphs, or animations, or a game. HTML is not very good at representing recursive behaviour, which makes tree structures harder to implement. Granted, you can get around this by reducing the tree structure to a flat list with an indentation level for each item in the list. But the point is that you have to resort to workarounds to get that sort of stuff to work. HTML just wasn't designed for imperative operations.

    This diagram illustrates how a modern HTML5 / CSS3 / JavaScript GUI may contain both simple and complex components, some of which are best defined using HTML, and some of which are best rendered via JavaScript.

    Not all parts of a modern GUI is best rendered using HTML

    Finding the right balance between how much is done declaratively and how much is done imperatively is not easy. Somehow we have to bridge or combine these two paradigms. But where on the axis is the optimal balance?

    The declarative / imperative axis.

    As mentioned earlier I have worked with several different GUI toolkits. In my opinion what has worked best is when you use a declarative approach for the overall composition of the GUI, and use an imperative approach when rendering the more complex GUI components. Look at this HTML template:

    <html>
    <head>
    </head>
    <body>
      
      <div>
          <div>My App</div>
          <div><table id="theTable" jqc-type="jqcTable"></table></div>
      </div> 
      
    </body>
    </html>    
    

    It contains a label (My App) which is easily declared and positioned using HTML. And it contains a data table which is a more complex GUI component, so only its location in the GUI is declared in the HTML. How it is rendered, bound to data and how it behaves when the user clicks rows etc. is implemented in JavaScript.

    This model contains a clear separation between the declarative and imperative paradigm. At least in the HTML template part. The implementations of the various components like the data table will be more muddy. But at least that is shielded from the developer making the HTML template. You are not tempted to specify part of it using HTML, and part of it using HTML-like directives. And you do not have to specify the whole GUI composition imperatively either.

    The above balance is how Flex works. You can specify the overall composition of a GUI in Flex using an XML format. You can then implement components in ActionScript which can be referenced in the XML. This isn't perfect, but at my current level of insight into GUI technologies, I feel this approach is most optimal I have seen.

    In my opinion AngularJS has positioned itself a step closer to the declarative end point than Flex. Yes, you can implement more coarse grained directives in AngularJS so you end up with an HTML template that is similar to the above. But that was never the selling point of AngularJS. It is usually the more fine grained directives that "Angularistas" praise.

    The declarative / imperative axis.

    After realizing that AngularJS was not what I was looking for, I actually started implementing my own GUI toolkit inspired partly Flex, and based on JavaScript and jQuery. I will get back to that later in this article.

    HTML5 Canvas & WebGL

    If you plan to render part of your GUI using HTML5 canvas or WebGL, you will also not get much help from AngularJS. Both HTML5 canvas and WebGL have imperative interfaces. The only HTML you see is the <canvas> element they both use to draw on. In fact, you will end up with a separation between HTML and JavaScript which is very similar to the separation I described earlier, where the HTML only contains a reference to where the components are located in the GUI, and not how they are rendered.

    The Intrusiveness of AngularJS Directives

    As already mentioned earlier, AngularJS directives are intrusive on your HTML template, just like JSP tag libraries etc. were. In order to "teach HTML new tricks" you end up with HTML full of non-HTML elements and attributes. Think about it for a while. When you need to teach HTML new tricks, that is a pretty good sign it is time to change to the imperative paradigm (JavaScript), except perhaps for very simple tricks.

    Another example of how the templating mechanism is intrusive is when you look at how many function calls that can (and will) be embedded in the HTML. Function calls on the $scope object. Before AngularJS it was "best practice" to keep function calls out of the HTML. For instance, you should not use the onclick event attributes on HTML elements, but rather attach event listeners via JavaScript. Somehow that was forgotten with AngularJS, and now we are back to embedding JavaScript function calls in the HTML.

    Designers Are Not Developers

    One argument I have seen often in favor of more advanced HTML templating systems is, that when no programming is involved in specifying the template, then designers can implement the HTML templates independently from the developers. If a designer knows HTML, then he or she will also be able to use the HTML templating system.

    I encountered this argument the first time related to JSP and its tag libraries. If a designer learned the tag libraries he or she could implement functionality without having to bother a developer. Adobe Dreamweaver - a popular HTML design tool - even has built-in support for JSP tag libraries. I have seen the same argument on blogs used in favor of the AngularJS HTML template system.

    I haven't actually worked in a place where this actually worked. Designers did not implement functionality, even with HTML-like tag libraries or directives. If this works where you are employed, I'd be happy to hear about your experiences.

    In my opinion the argument is based on a false premise. The premise that if a designer knows the HTML syntax then they can all of a sudden perform programming tasks, given an HTML-like templating system. While this is theoretically true, the premise mistakes syntax for semantics.

    A designer is primarily concerned with looks while a developer is primarily concerned with behaviour. If you give a designer an HTML-like syntax and asking her to add behaviour to the web page, there is a pretty good chance that she will think "but what does that have to do with design?". It is not what her mind is trained to do, regardless of the syntax.

    The same is true the other way around. A developer does not all of a sudden become a designer just because they get a cool graphical API at their disposal. Looks and behaviour are different semantic areas of an application. These semantics are what separates the designer's work from the developer's - not syntax or tools.

    There is a significant difference between specifying the looks and behaviour of an application, even if the syntax used for the two tasks is the same.

    AngularJS Without Directives?

    AngularJS directives are one of the core features of AngularJS. Take them out, and what do you really have left? The whole framework revolves around them and their binding to the $scope object, the way AngularJS is designed now. Thus, if you choose to use AngularJS in your project, the directives is a phenomenon you will have to live with.

    Two-way Data Binding

    Another feature that seem to impress people about AngularJS (apart from its directives), is the two-way data binding between form fields and model properties. However, in a real life application this is not always that useful.

    AngularJS will copy the values of form fields into your model object automatically, if the form field values are valid. If a form field is not valid, that model field is left empty. That means, that if you bind your form fields to an object in an array which you are using to display e.g. a data table with, those fields are cleared in the data table too. Or at least in your data model.

    You often don't want that. You only want data to be copied from form fields if they represent a valid coherent collection of data. In other words, you don't want any data copied into your original data unless all data in the form is valid. And you don't want any data copied into your model if the user ends up pressing the "cancel" button.

    Second, you will often not even want the data copied directly into your data objects until the data has been sent to the server (typically using a remove create or update service), and the server has responded that the data was accepted. Then, and only then do you want your data model on the client updated to reflect the new values. The following diagram illustrates this data flow:

    The normal data flow of a GUI app.

    The two-way data binding in AngularJS kind of gets in the way of creating this data flow. You will end up binding your form fields to model variables that are separate from your model data objects, to avoid polluting your data objects. That way you copy data from a model object into form field model properties, further into form fields, then back into form field model properties, then send them to the server, and if that succeeds, you can update your original model data object. Here is the data flow you will end up with in AngularJS:

    The data flow in an AngularJS app.

    While you can get an app to work with this data flow, it kind of takes the glamour away from two-way data binding.

    Critique Summary

    We do indeed need better frameworks to make it easier to develop larger HTML / JavaScript applications, but I don't feel that AngularJS has chosen the right approach. We do need to find a balance between the declarative HTML and the imperative JavaScript, but I feel that AngularJS has gone too far in the declarative direction. We do need to find ways to bind data to HTML elements / GUI components, but the one-way data binding in the AngularJS directives and two-way data binding in forms can be done better. But this is just my opinion. The whole purpose of this article was to help you form your own opinion.

    An Alternative

    As mentioned earlier I have been looking a long time for the "perfect" GUI toolkit, and when AngularJS turned out not to be what I was looking for either, I finally decided to make an attempt at a GUI toolkit myself.

    The GUI toolkit is inspired by Flex and based on jQuery. The toolkit is centered around a page controller which scans the HTML page for elements referencing GUI components. For each GUI component reference found, a corresponding JavaScript object is created. These objects (components) are then kept internally in the page controller.

    The page controller helps you avoid the "jQuery soup" which often occurs in larger jQuery apps. The page controller helps you break the code into components and modules, and keep references to instantiated components and modules etc.

    The component approach avoids the DOM-centric code you can easily end up with in jQuery powered web apps, especially if they use jQuery plugins as GUI components. Therefore the toolkit does not use jQuery plugins for its GUI components.

    The toolkit is called jqComponents (as in jQuery Components) and can be found at jqcomponents.com

    Whether this approach will be closer to the "perfect" I am looking for than AngularJS is too early to say. Only time will tell. The initial proof-of-concept looks promising though (but I am biased of course).

    More AngularJS Critics

    I am not the only one to criticize AngularJS. I have read a few other great articles critizing different aspects of AngularJS than what I have included here. I have supplied a list of the best ones below. They are worth reading!

    Why You Should Not Use AngularJS