Angular JS – ngRepeat with control variables

Within an ng-repeat directive I can have various information about the status of the loop.To access these informations Angular provides a set of special variables (with prefix “$”). I can also use the ng-class-event/ng-class-odd to have an alternating style through the rows.

<h3>Display data in a table</h3>
<table>
    <tr>
        <th>Index</th>
        <th>First</th>
        <th>Last</th>
        <th>Odd</th>
        <th>Name</th>
        <th>City</th>
        <th>Country</th>
    </tr>
    <tr ng-repeat="place in places | orderBy : 'Country'" ng-class-even="'even'" ng-class-odd="'odd'">
        <td>{{$index}}</td>
        <td>{{$first}}</td>
        <td>{{$last}}</td>
        <td>{{$odd}}</td>
        <td>{{place.Name}}</td>
        <td>{{place.City}}</td>
        <td>{{place.Country | uppercase}}</td>
    </tr>
</table>

I can also use an expression to determine the class name within the ng-class directive. This can be don using the {…} inside the directive value. For example, if I want to have a particular class just for even rows I can write a similar expression:

ng-class="{'even': $index % 2 == 0}"
Advertisements

Angular JS – Multiple Controllers

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Angular JS</title>
</head>
<body data-ng-app="myApp">
    <div data-ng-controller="myController1">
        <p>The full name is {{ firstName + " " + lastName }}</p>
    </div>
 
    <div data-ng-controller="myController2">
        <p>The full name is {{ firstName + " " + lastName }}</p>
    </div>
 
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
 
    <script>
        var app = angular.module("myApp", []);
 
        app.controller("myController1", function ($scope) {
            $scope.firstName = "John";
            $scope.lastName = "Doe";
        });
 
        app.controller("myController2", function ($scope) {
            $scope.firstName = "Tizio";
            $scope.lastName = "Caio";
        });
    </script>
</body>
</html>

Angular JS – Defer, Promise and Resolve + Minification

There are cases in which is not sufficient to rely on the Angular functions to perform the necessary operation within a controller. In these cases, if the operations are asynchronous, will be necessary to wait for their completion before to be able to add their result to the $scope object.

The problem is that outside the Angular’s functions (such as the $http.get(), that is asynchronous, but is managed by Angular to work properly) there are issues when you try to assign something on the $scope object from an asynchronous function’s callback.

In these cases is possible to use the premises mechanism, that is accessible from Angular by adding the $q parameter. A premise allow you to assign a certain code block (defined inside the then() method) to the time in which a particular data becomes available. The data’s availability is notified through the resolve() method, that triggers the execution of the then() method with the data’s value passed as parameter.

Here is an example of how you could make the binding work if you decide to not use the $http.get() to read a remote json, but a normal jQuery ajax call (note that without the premises mechanism it would not work):

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Angular JS</title>
</head>
<body>
    <div data-ng-app="myApp" data-ng-controller="myController">
 
        <!--
            I can use premises to defer the assignation of an
            element to when an asynchronous operation has finished
            -->
        <h3>Deferred</h3>
        <ul>
            <li data-ng-repeat="place in places">
                <p>The place is: {{ place.Name + ', ' + place.Country }}</p>
            </li>
        </ul>
        <hr />
    </div>
 
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
 
    <script>
        var app = angular.module("myApp", []);
 
        app.controller("myController", ["$scope", "$q", function myController($scope, $q) {
            var page = "/JS/Feeds/testFeed.js";
 
            var d = $q.defer();
            d.promise.then(function (p) {
                $scope.places = p;
            });
 
            $.ajax({
                dataType: "json",
                url: page,
                success: function (response) {
 
                    //Add the response to the model
                    d.resolve(response);
                }
            });
        }]);
    </script>
</body>
</html>

Minification handling

You can note that this time the controller is defined within an array and is preceded by the parameters’ names expressed as strings. This is useful because for Angular the parameters’ names are important, not just the positions (for example in this case the name of the second parameter is $q, but if I had put a different name (such as $http) it would give me a different object). The problem is that the minification process tends to rename them, with the result that the controller is not able to work properly. By writing in this way Angular is still able to understand which parameters we are referring to.

Angular JS – Binding HTML and CSS Class

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Angular JS</title>
</head>
<body>
    <style>
        .box
        {
            display: block;
            width: 100px;
            height: 100px;
        }
 
        .red
        {
            background-color: red;
        }
 
        .blue
        {
            background-color: blue;
        }
    </style>
 
    <div data-ng-app="myApp" data-ng-controller="myController">
 
        <!--
            I can bind the HTML content of an element with the "data-ng-bind-html"
            directive. To do this I must include the sanitization JS and add it
            as a dependancy to the app. The sanitization service check that the
            HTML code is safe (not containing scripts or others XSS exploits)
            -->
        <h3>Binding HTML content</h3>
        <p>
            HTML content:
            <input type="text" data-ng-model="htmlContent" />
        </p>
        <div data-ng-bind-html="htmlContent">
        </div>
        <hr />
 
        <!--
            I can bind the class with the "data-ng-class" directive
            -->
        <h3>Binding class</h3>
        <p>
            <div data-ng-class="'box ' + myClass">
            </div>
        </p>
        <button data-ng-click="changeColour()">Change colour</button>
    </div>
 
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.3/angular-sanitize.js"></script>
 
    <script>
        var app = angular.module("myApp", ["ngSanitize"]);
 
        app.controller("myController", function ($scope) {
            $scope.htmlContent = "HTML content <strong>strong text</strong>";
            $scope.myClass = "red";
            $scope.changeColour = function () {
                $scope.myClass = ($scope.myClass == "red" ? "blue" : "red");
            }
        });
    </script>
</body>
</html>

Binding HTML without limitations

Ok, using the sanitization we can bind some HTML to our view. But can we really bind any HTML content? Of course no. Angular is checking behind the scenes and will automatically remove the HTML parts that he doesn’t like, preventing them to be rendered. So, how to do in these particular cases? It’s a bit more complicated.. first of all we have to create this function within our controller:

angular.module("myApp.myControllers").controller("myController", ["$scope", "$sce", function ($scope, $sce) {
    $scope.trustAsHtml = function (html) {
        return $sce.trustAsHtml(html)
    };
}]);

With this function we are telling Angular to trust us and just to render the HTML we are telling him to render. Now we are ready to render whatever we want just using the new function in this way:

<div class="content" ng-bind-html="trustAsHtml(html)">
</div>

Binding class name based on a condition

I can use the ngClass directive to define a mapping between the result of a condition and a class name. An interesting thing is that I can still use the normal class attribute for the constant part. The mapping is represented by a JS object for which each property name is a possible class name and the correspondent value is the related condition.

<div class="box" ng-class="{'type1': value=1, 'type2': value=2}">
</div>

Angular JS – Working with Modules

myApp.js
myCtrl.js

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Angular JS</title>
</head>
<body>
 
    <!--
        I can use modules to avoid using global function for my controllers.
        To do this I define an app object, registered with a particular name,
        then I refer that name as the app name in the "data-ng-app" directive
        -->
    <div data-ng-app="myApp" data-ng-controller="myController">
        <h3>Modules</h3>
        <p>The full name is {{ firstName + " " + lastName }}</p>
    </div>
 
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
    <script src="JS/Default05/myApp.js"></script>
    <script src="JS/Default05/myCtrl.js"></script>
 
    <script>
 
        //I moved this code to myApp.js!!!
 
        ////This is the app object
        //var app = angular.module("myApp", []);
 
        //I moved this code to myCtrl.js!!!
 
        ////I'm adding the controller to the app object
        //app.controller("myController", function ($scope) {
        //    $scope.firstName = "John";
        //    $scope.lastName = "Doe";
        //});
    </script>
</body>
</html>

Angular JS – Binding Attributes & Events

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Angular JS</title>
</head>
<body>
    <div data-ng-app="" data-ng-controller="myController">
 
        <!--
            I can use the "data-ng-disabled" directive
            to bind the abilitation of a control
            -->
        <h3>Binding abilitation</h3>
        <button data-ng-disabled="buttonDisabled">Click Me!</button>
        <p>
            Button disabled:
            <input type="checkbox" data-ng-model="buttonDisabled" />
        </p>
        <hr />
 
        <!--
            I can use the "data-ng-show" directive
            to bind the abilitation of a control
            -->
        <h3>Binding visibility</h3>
        <button data-ng-disabled="buttonDisabled" data-ng-show="buttonShowed">Click Me!</button>
        <p>
            Button showed:
            <input type="checkbox" data-ng-model="buttonShowed" />
            Button disabled:
            <input type="checkbox" data-ng-model="buttonDisabled" />
        </p>
        <hr />
 
        <!--
            I can handle an event to make some operation in
            the model with the "data-ng-click" directive
            -->
        <h3>Event handling</h3>
        <button data-ng-click="count = count + 1">Click me!</button>
        <p>You clicked {{ count }} times</p>
        <hr />
 
        <!--
            I can handle an event from the controller
            -->
        <h3>Event handling from controller</h3>
        <button data-ng-click="countIncrement()">Click me!</button>
        <button data-ng-click="toggleAbilitation()">Toggle abilitation</button>
        <p>You clicked {{ count }} times</p>
    </div>
 
    <script>
        function myController($scope) {
            $scope.buttonDisabled = true;
            $scope.buttonShowed = true;
            $scope.count = 0;
 
            //These are event handlers
            $scope.countIncrement = function () {
                $scope.count++;
            };
            $scope.toggleAbilitation = function () {
                $scope.buttonDisabled = !$scope.buttonDisabled;
            }
        }
    </script>
 
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
</body>
</html>

Angular JS – Remote JSon Binding

testFeed.js

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Angular JS</title>
</head>
<body>
    <style>
        table, th, td
        {
            border: 1px solid grey;
            border-collapse: collapse;
            padding: 5px;
        }
 
            table tr:nth-child(odd)
            {
                background-color: #f1f1f1;
            }
 
            table tr:nth-child(even)
            {
                background-color: #ffffff;
            }
    </style>
 
    <div data-ng-app="" data-ng-controller="myController">
 
        <!--
            I can get the model from a remote jSon and bound it to the
            controls. In this way is also possible to fetch data from a db
            -->
        <h3>Remote model binding</h3>
        <ul>
            <li data-ng-repeat="place in places">
                <p>The place is: {{ place.Name + ', ' + place.Country }}</p>
            </li>
        </ul>
        <hr />
 
        <!--
            It's easy to use the "data-ng-repeat" to display data in table
            -->
        <h3>Display data in a table</h3>
        <table>
            <tr>
                <th>Name</th>
                <th>City</th>
                <th>Country</th>
            </tr>
            <tr data-ng-repeat="place in places | orderBy : 'Country'">
                <td>{{place.Name}}</td>
                <td>{{place.City}}</td>
                <td>{{place.Country | uppercase}}</td>
            </tr>
        </table>
    </div>
 
    <script>
        function myController($scope, $http) {
            var site = "";
            var page = "/JS/Feeds/testFeed.js";
 
            //Get jSon data from the server
            $http.get(site + page).success(function (data, status, headers, config) {
 
                //Add the response to the model
                $scope.places = data;
            });
        }
    </script>
 
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
</body>
</html>

Advanced use of $http

Even though we can use $http.get() and $http.post() to refer the main two HTTP methods while requiring remote data, there is a more general way to use this object. Indeed we can just invoke $http() itself with a JSon configuration object. Here some examples:

$http({
    url: 'api/me-entity/save',
    method: 'POST',
    data: entityModel,
    headers: { 'Content-Type': 'application/json' }
}).success(function (data) {
    alert('success');
}).error(function (error) {
    alert('error');
});

$http({
    url: 'api/me-entity/get/' + entityId,
    method: 'GET',
    headers: { 'Content-Type': 'application/json' }
}).success(function (data) {
    alert('success');
}).error(function (error) {
    alert('error');
});

Angular JS – Controllers & Filters

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Angular JS</title>
</head>
<body>
 
    <!--
        Normally I don't use the "data-ng-init" directive.
        Instead I use a controller to control the angular application.
        I use the "data-ng-controller" directive to refer the controller
        -->
    <div data-ng-app="" data-ng-controller="myController">
        <h3>Controllers</h3>
        <p>
            First Name:
            <input type="text" data-ng-model="person.firstName" />
        </p>
        <p>
            Last Name:
            <input type="text" data-ng-model="person.lastName" />
        </p>
        <p>Full Name: {{person.firstName + " " + person.lastName}}</p>
        <p>Full Name: {{person.fullName()}}</p>
        <hr />
 
        <!--
            I can use filters on binding to specify a particular format
            -->
        <h3>Binding filters</h3>
        <p>Full Name uppercase: {{person.fullName() | uppercase}}</p>
        <p>Full Name lowercase: {{person.fullName() | lowercase}}</p>
        <p>
            Value:
            <input type="text" data-ng-model="value" />
        </p>
        <p>Currency value: {{value | currency}}</p>
        <hr />
 
        <!--
            I can use filters on loops to specify a particular order
            -->
        <h3>"OrderBy" filter for loops</h3>
        Names
        <ul>
            <li data-ng-repeat="name in names | orderBy:'toString()'">
                <p>The name is: {{ name }}</p>
            </li>
        </ul>
        Articles by name
        <ul>
            <li data-ng-repeat="article in articles | orderBy:'name'">
                <p>The article is: {{ article.name + ' ' + (article.price | currency) }}</p>
            </li>
        </ul>
        Articles by price
        <ul>
            <li data-ng-repeat="article in articles | orderBy:'price'">
                <p>The article is: {{ article.name + ' ' + (article.price | currency) }}</p>
            </li>
        </ul>
        <hr />
 
        <!--
            I can use filters on loops to filter a subset of elements.
            To do this I must use a dedicated model property (implicitly
            created by referring with the "data-ng-model" directive)
            -->
        <h3>"Filter" filter for loops</h3>
        <p>
            Article filter:
            <input type="text" data-ng-model="articleFilter" />
        </p>
        <p>Article filter: {{articleFilter}}</p>
        <ul>
            <!--
                The filter will show every article for which the filter
                value matches a part of any of his values (in this case
                can be a part of the name or a part of the price)
                -->
            <li data-ng-repeat="article in articles | filter:articleFilter | orderBy:'price'">
                <p>The article is: {{ article.name + ' ' + (article.price | currency) }}</p>
            </li>
        </ul>
    </div>
 
    <script>
 
        //This is the controller constructor. The $scope argument is
        //the application for which the controller has been instantiated
        function myController($scope) {
 
            //Through the $scope object I
            //can define an hardcoded model
            $scope.person = {
                firstName: "John",
                lastName: "Doe",
 
                //This is a calculated property. Must
                //be referred as a function for binding
                fullName: function () {
                    var x = $scope.person;
                    return x.firstName + " " + x.lastName;
                }
            };
            $scope.value = 50;
            $scope.names = ["pippo", "pluto", "tizio", "caio", "adamo", "eva"];
            $scope.articles = [{ name: "lamp", price: 120 }, { name: "chair", price: 50 },
                { name: "table", price: 100 }, { name: "glass", price: 20 }];
        }
    </script>
 
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
</body>
</html>

JSon filter

I can use this filter when i want to bind a complex object, to display his JSon code. Indeed the JSon code is returned also without the filter, but with the filter is formatted in a better way.

Angular JS – Base Commands

https://angularjs.org

Angular is a framework with many features to create dynamic web apps. It can handle the MVC pattern in a very simple way with a very efficient binding mechanism from JS models to HTML views. In respect with other frameworks (such as Knockout) is much more powerful and easy to use, but the real difference is that it’s not just an MVC framework. It also includes many features for which, in a real application, it would be necessary to use different frameworks together, such as the SPA routing. Except for JQuery and the testing frameworks (such as Jasmine and Mocha) it covers a good part of what is needed to create a modern web app.

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <title>Angular JS</title>
</head>
<body>
 
    <!--
        The container with the "data-ng-app"
        directive is the root of an angular application
        -->
    <div data-ng-app="" data-ng-init="name='John'; surname='Smith';
        article={name:'laptop',price:750,quantity:10}; values=[1,2,3,5,8,13]">
 
        <!--
            I can calculate expressions by putting them between {{}}
            -->
        <h3>Expressions</h3>
        <p>My first expression: {{ 5 + 5 }}</p>
        <hr />
 
        <!--
            I can define an hardcoded model inside the "data-ng-init"
            directive of the container and bind it to the elements'
            content with the "data-ng-bind" directive
            -->
        <h3>Binding</h3>
        <p>The name is: <span data-ng-bind="name"></span></p>
        <p>The surname is: <span data-ng-bind="surname"></span></p>
        <p>The article is: <span data-ng-bind="article.name"></span></p>
        <p>The 4rd value is: <span data-ng-bind="values[3]"></span></p>
        <hr />
 
        <!--
            I can use model elements inside expressions
            -->
        <h3>Expressions with model</h3>
        <p>The articles total price is: {{ article.price * article.quantity }}</p>
        <p>The full name is: {{ name + ' ' + surname }}</p>
        <hr />
 
        <!--
            I can directely bind expressions to the elements' content
            -->
        <h3>Binding expressions</h3>
        <p>The articles total price is: <span data-ng-bind="article.price * article.quantity"></span></p>
        <p>The full name is: <span data-ng-bind="name + ' ' + surname"></span></p>
        <hr />
 
        <!--
            I can bind a model element to an input
            element with the "data-ng-model" directive
            -->
        <h3>Binding input</h3>
        <p>
            The name is:
            <input type="text" data-ng-model="name" />
        </p>
        <p>
            The article price is:
            <input type="text" data-ng-model="article.price" />
        </p>
        <p>
            <!--
                I can refer to a not existent model
                element. It will be created on the fly
                -->
            The implicitly created value is:
            <input type="text" data-ng-model="implicitlyCreatedValue" />
        </p>
        <p>The name is: {{ name }}</p>
        <p>The article price is: {{ article.price }}</p>
        <p>The implicitly created value is: {{ implicitlyCreatedValue }}</p>
        <hr />
 
        <!--
            I can repeat an element for each element of
            an array with the "data-ng-repeat" directive
            -->
        <h3>Looping through an array</h3>
        <ul>
            <li data-ng-repeat="value in values">
                <p>The value is: {{ value }}</p>
            </li>
        </ul>
    </div>
 
    <!--
        Including jQuery before angular is not mandatory, but if I do
        then angular will start to use jQuery for DOM manipulation 😉
        -->
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
    <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.22/angular.min.js"></script>
</body>
</html>

I can bind the content of each attribute also without a specific binding directive, but just using the {{}}. For example I can bind a method that return a CSS style rule in this way:

style="{{ myMethod(myScopeObject) }}"