First AngularJs example

If you are looking around for a new job as .NET developer, all companies are asking you AngularJs. Then I’m starting to learn it and I share with you the secret of this framework.

I’m assuming you are a .NET developer like me and you want to learn AngularJs and then I won’t explain you the basis of HTML.

Open Visual Studio and create a new solution with ASP.NET Empty web Site.

AnguarJS1-CreateEmptySolution-VisualStudio2017

Now you have your project.

AnguarJS1-EmptySolution-VisualStudio2017

Add from NuGet AngularJS.Core.

AnguarJS1-AddAngularJs-from-NuGet-VisualStudio2017

Done. We start now with a little complicate example. Two examples.

StartHere.html

<!DOCTYPE html>
<html ng-app="myApp">
<head>
    <meta charset="utf-8" />
    <title></title>
    <script src="Scripts/angular.min.js"></script>
</head>
<body ng-controller="ExampleController">
    <h1>Game setup</h1>
    <div ng-repeat="player in players" 
        ng-init="playerIndex = $index">
        <ng-include src="'player.html'"></ng-include>
    </div>
    <script>
        (function () {
            "use strict";
            var myAppModule = angular.module('myApp', []);

            myAppModule.factory('playerService', function () {
                var playerCount = 0;
                var createDefaultPlayer = function () {
                    playerCount += 1;
                    var player = {
                        name: "",
                        prevName: ""
                    };

                    player.onNameFocused = function () {
                        player.prevName = player.name;
                    };
                    return player;
                }

                return {
                    createPlayer: function (name) {
                        var player = createDefaultPlayer();
                        player.name = name;
                        return player;
                    },
                    getPlayerCount: function () {
                        return playerCount;
                    }
                };
            });

            myAppModule.controller('ExampleController', ['$scope', 'playerService',

                function ($scope, playerService) {

                    $scope.players = [playerService.createPlayer('Player1'),
                        playerService.createPlayer('Player2'),
                        playerService.createPlayer('Player3')];

                }

            ]);
        }());
    </script>
</body>
</html>

player.html

<h2>Player {{$playerIndex + 1}}</h2>
<label>Name:</label>
<input type="text" placeholder="Enter Player {{$playerIndex + 1}}" 
    ng-model="player.name" ng-focus="player.onNameFocused()" />
<h3 ng-show="player.name">
    Player {{$playerIndex + 1}} name is {{player.name}}
</h3>
<h3 ng-show="player.prevName">
    Prev Player {{$playerplayerIndex + 1}} name was 
    {{player.prevName}}
</h3>

Explanation

JavaScript frameworks such as Backbone.js, knockout.js, AngularJs and others addressed the problems of scalability, reusability, and testability by embracing a design pattern traditionally used by server-side frameworks.

This pattern is called Model-View-Controller (MVC), and it is an established pattern that was originally introduced in the 1970s. You should already be familiar with it from the ASP.NET MVC fundamentals, but I will revisit it here for reference.

Technically, AngularJS uses a variant of the MVC, which is closer to the Model-View-ViewModel (MVVM) pattern, but the definition of MVC from the next section still applies to it. One of the core members of the AngularJS team declared the main design pattern behind AngularJS as being “Model-View-Whatever works for you” (MVW or MV*) in this post at https://plus.google.com/+AngularJS/posts/aZNVhj355G2.

The design pattern is specific for applications with user interfaces and introduces a separation between the following aspects:

  • Model: This is the application data and the business logic associated with it
  • View: This is the output of the application data in any form that can be consumed or manipulated by a user
  • Controller: This is the logic to get data from the View to the Model and back, and to manage any interaction with the View or the Model

The first highlighted attribute is ng-app, which has a value this time around. The myApp value represents the unique identifier of the current AngularJS application. The next highlighted code initializes a new AngularJS component called module, which will be used via the myApp identifier to bootstrap the AngularJS application.

A module is a container-like object with a unique identifier that groups together the AngularJS components used to build an application: controllers, directives, and others, such as providers, factories, services, values, constants, animations, and filters. The module has methods that are specific to the AngularJS application components I mentioned.

The module controller function takes the controller name and controller constructor function as arguments.

The first highlighted snippet is the service definition that looks similar to a controller definition, with the exception that it returns an object that represents the service factory. This object is used to create the service instance that will be injected in all of the AngularJS components that have this service declared as a dependency.

In the new service, we transformed the previous controller code into a function called createDefaultPlayer(), which will create a new object that represents a player. The service instance has a method to create a new player with a predefined name called createPlayer(name). The service factory function will keep track of how many player objects were created using the playerCount variable. The variable will be returned by the service instance function, getPlayerCount(). On a side note, you can see the revealing module pattern in action here. Although the script section is now bigger, we obtained new features such as code reusability and flexibility to provide more complex functionality than before.

There are other methods available on the module interface to declare an AngularJS service, such as service, value, and constant. The service method will use a constructor function to create the service instance, while the value method will use an already created service instance that will be passed unchanged to the AngularJS injector. The constant method is similar with the value method, with the difference that it will be available during the configuration phase of the application module. The factory method is one of the most flexible methods, and it will be the most frequently used method in the rest of the examples from this book. It allows additional configuration to the returned service instance, and you can even keep track of data outside of the service instance, such as with the playerCount variable from the previous example.

We have used a lot of directives in the examples presented so far, and most of them used the ng- prefix. When you take a look at the directives’ documentation pages at https://code.angularjs.org/1.2.15/docs/api, you will notice that the directive names appear slightly different—ng-app is ngApp and ng-controller is ngController. AngularJS removes any data- or x- prefixes from the HTML markup and converts the -, _, and : characters to a camel case directive name. From now on, we will refer to different directives using the names from the AngularJS documentation.

We will explore some important built-in directives and see how to build custom directives. Looking back at the previous example, the HTML markup seems to have been duplicated for the two players. There is a built-in directive called ngRepeat that allows us to remove the duplicated markup as highlighted in the next example.

The ngRepeat directive works with a collection of objects and repeats an HTML markup section for each item in the collection. We created an array of player items in the controller that is used in the ngRepeat directive. The first highlighted code section shows the expression used to iterate through the collection, and the div element that has the directive is repeated for each item in the collection. The player variable defined in the ngRepeat expression is only available inside of the directive. The ngRepeat directive has its own scope that contains other directive-specific variables such as $index, which has been used in the next highlighted code snippet. This variable of the type number keeps track of the current collection item index, and there are other directive-specific Boolean variables available: $first, $middle, $last, $odd, and $even.

The example works for HTML markup that repeats a single element. When the HTML markup that needs repeated elements has separate start and end elements, you need to use two different directive attributes. The first is ng-repeat-start, which is a renamed ng-repeat directive that needs to be used on the start HTML element. The second is ng-repeat-end, which does not have an expression value and is used on the HTML element that ends the markup that needs repeated elements. The previous example of the body element content can now be written using the h2 element as the start of the repeated markup and the h3 element as the end, as shown in the following code:

  <h1>Game setup</h1>
  <div>
    <h2 ng-repeat-start="player in players">
        Player {{$index + 1}}
    </h2>
    <label>Name:
    <input type="text" placeholder="Please enter player {{$index + 1}} name" 
        ng-model="player.name" ng-focus="player.onNameFocused()">
    <h3 ng-show="player.name">Player {{$index + 1}} name is {{player.name}}.</h3>
    <h3 ng-repeat-end ng-show="player.previousName">
        Previous Player {{$index + 1}} name was 
        {{player.previousName}}.
    </h3>
  </div>

The ngRepeat directive example is very useful when we need to manipulate the HTML for a specific application view. However, I can easily imagine scenarios where the HTML for a player has to be reused between different views. If there is a single player game, we want to see only one player editing form rather than two. AngularJS offers a simple but powerful solution through the ngInclude directive. This directive allows the referencing of a separate file that will be loaded and rendered in the current HTML view by AngularJS.

To introduce this directive, I had to change the HTML for the ngRepeat example and add a new file that contains the player HTML markup.

The first highlighted attribute is a new directive, ngInit, that evaluates an arbitrary expression. Although this directive can be used anywhere, it is best practice to only use it in the context of the ngRepeat directive. We use it to create a new scope property that is an alias of the $index variable from the ngRepeat directive. The reason behind this alias is to allow the reuse of the player markup in contexts where there is no enclosing ngRepeat directive.

The next highlighted element is the ngInclude directive, which fetches the referenced player.html file, renders it, and creates a new scope for it. The scope inherits the current ngRepeat iteration scope and its player and playerIndex properties. The last highlighted expression shows how the property created by ngInit is used in player markup.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.