Thursday 14 January 2016

Create a Basic Sample Angular JS Application using Typescript

In this post we are going to see how to create a sample angular js application using Typescript, visual studio is a best editor for developing a Typescript applications, because it will compile and gives the intellisense  for the typings.


First we have to create a empty Asp.Net web project in visual studio, then we have to download the Typing file for angular to start the code. angular.d.ts, angular-route.d.ts , 





Now we will see a basic sample in which we have to create a module and a controller with one method. To start with Typescript we need the following files need to be added in our project. Don't consider the reference path , just find the file name from the list.

    <script type="text/javascript" src="scripts/angular.js"></script>
    <script type="text/javascript" src="scripts/angular-route.js"></script>
    <script type="text/javascript" src="scripts/jquery-1.9.1.js"></script>
    <script type="text/javascript" src="scripts/bootstrap.js"></script>
    


Install the Typescript from the following link if not present in visual studio 
https://www.microsoft.com/en-us/download/details.aspx?id=48593

Once finish the download the above typing file , add that in your project.


/// <reference path="../scripts/typings/angularjs/angular.d.ts" />
/// <reference path="../scripts/typings/angularjs/angular-route.d.ts" />

Now create a typescript file app.ts and add the above reference in the first two line to get the intellisense while coding.

We have to do the things in order so first we have to create a model, then interface, then controllers, finally create module.
Get a Employee List is the sample we are currently trying 

Create a Model:
 In Typescript we can define the custom data types in model, then we can refer it in variable type, Now here Employee is the Type, so the sample will be like following.

app.ts
/// <reference path="../scripts/typings/angularjs/angular.d.ts" />
/// <reference path="../scripts/typings/angularjs/angular-route.d.ts" />

module DotnetVisio.Model {

    export class Employee {
        id: number;
        name: string;
        address: string;
    }
}


when you save the file it will generate the Js file, the output file will be.

Generated code in app.js
/// <reference path="../scripts/typings/angularjs/angular.d.ts" />
/// <reference path="../scripts/typings/angularjs/angular-route.d.ts" />
var DotnetVisio;
(function (DotnetVisio) {
    var Model;
    (function (Model) {
        var Employee = (function () {
            function Employee() {
            }
            return Employee;
        })();
        Model.Employee = Employee;
    })(Model = DotnetVisio.Model || (DotnetVisio.Model = {}));
})(DotnetVisio || (DotnetVisio = {}));


Create a Interfaces:
Now we have to create a Interface for Scope and that need to be derived from the ng.scope, because we have to specify or add the things which are need to be there in scope, then we have to specify that scope type in controller. Here in this sample we are going to add the IMainScope which is dervies from ng.IScope , then later we will specify that type in the controller , In sample we are specifying that scope must have the three property and a method.


IMainScope extends ng.IScope


app.ts
module DotnetVisio.Interfaces {
    export interface IMainScope extends ng.IScope {
        name: string;
        title: string;
        Employees: Array<Model.Employee>;
        getEmployees(): void;
    }
}


Create a Controller:
Creating a controller is little bit different from the normal angular js applications, Generally while creating controller we must pass the dependency as a parameters and map the attributes to the scope inside the controller like below.

Normal Angular JS Controller Code:
app.controller('MainController', ['$scope', function ($scope) {
        $scope.name = "Employees";
        $scope.title = "Angular Sample";

        $scope.getEmployees = function () {
            $scope.Employees = [
                { id: 1, name: "Rajesh", address: "Chennai" },
                { id: 2, name: "Suresh", address: "California" },
                { id: 3, name: "Ramu", address: "Pune" },
                { id: 4, name: "Shiny", address: "London" }
            ]
        }

    }]);

Now we will see how to create a equivalent Typescript code, in typescript we have to specify the dependency to inject using the $inject as Static array property or directly write as controller.$inject = [];

app.ts
module DotnetVisio.Controllers {

    export class MainController{
        private $scope: Interfaces.IMainScope;

        constructor($scope: Interfaces.IMainScope) {
            var ViewModel = this;
            ViewModel.$scope = $scope;
            ViewModel.$scope.title = "Angular Sample";
            ViewModel.$scope.name = "Employees";
            ViewModel.InitMethods();
        }

        private InitMethods(): void {
            var ViewModel = this;

            ViewModel.$scope.Employees = [];

            ViewModel.$scope.getEmployees = function () {

                ViewModel.$scope.Employees =  <Model.Employee[]>[
                    <Model.Employee>{ id: 1, name: "Rajesh", address: "Chennai" },
                    <Model.Employee>{ id: 2, name: "Suresh", address: "California" },
                    <Model.Employee>{ id: 3, name: "Ramu", address: "Pune" },
                    <Model.Employee>{ id: 4, name: "Shiny", address: "London" }
                ];

            }
            
        }
        
        static $inject = ['$scope'];
    }  
}

When you see above code we are injecting the $scope in $inject Array property to the controller, it is a static one, it can be declare in two ways one is declare as a static inside the controller or outside the controller function just add a property like MainController.$inject = ['$scope'], another thing here we have to notice is we are assign a this keyword to the variable named ViewModel, this is because the current constructor function instance refers to this, we must add the $scope property to the Controller function instance.so this.$scope is added from the injector , and also we are specifying the type of the scope as IMainScope, which have three properties and a method, after assign the $scope to the instance we have to access it through the instance variable, now there is a question we can use the this keyword instead of doing that why we have to create a another variable and assign the instance to that, because this parameter refers in root function cant be the same of child function. 

For example Here InitMethods() is a function which is used to map the methods in the scope $scope, when we use the this parameter inside the method is not the same as the this parameter used inside the method getEmployees, how means when you try to access the property Employees inside the getEmployees method like below this.$scope.Employees = [], it will show error as undefined, because both the this are refers to two different ones, now we are need the outer scope this, so to access the instance, we are maintain the instance in a variable named ViewModel, then access that inside the getEmployees() method will able to access everything in $scope like Employees Property.


Generated code in app.js
var DotnetVisio;
(function (DotnetVisio) {
    var Controllers;
    (function (Controllers) {
        var MainController = (function () {
            function MainController($scope) {
                var ViewModel = this;
                ViewModel.$scope = $scope;
                ViewModel.$scope.title = "Angular Sample";
                ViewModel.$scope.name = "Employees";
                ViewModel.InitMethods();
            }
            MainController.prototype.InitMethods = function () {
                var ViewModel = this;
                ViewModel.$scope.Employees = [];
                ViewModel.$scope.getEmployees = function () {
                    ViewModel.$scope.Employees = [
                        { id: 1, name: "Rajesh", address: "Chennai" },
                        { id: 2, name: "Suresh", address: "California" },
                        { id: 3, name: "Ramu", address: "Pune" },
                        { id: 4, name: "Shiny", address: "London" }
                    ];
                };
            };
            MainController.$inject = ['$scope'];
            return MainController;
        })();
        Controllers.MainController = MainController;
    })(Controllers = DotnetVisio.Controllers || (DotnetVisio.Controllers = {}));
})(DotnetVisio || (DotnetVisio = {}));


Create a Module:
Module must be created inside a module pattern like below and refers the controller with name and refers the function as second parameter

app.ts
module DotnetVisio.Module {

    var app = angular.module('app', []);
    app.controller('MainController', Controllers.MainController);    

}

Generated code in app.js
var DotnetVisio;
(function (DotnetVisio) {
    var Module;
    (function (Module) {
        var app = angular.module('app', []);
        app.controller('MainController', DotnetVisio.Controllers.MainController);
    })(Module = DotnetVisio.Module || (DotnetVisio.Module = {}));
})(DotnetVisio || (DotnetVisio = {}));


Html :
Now in html we have to refers all the JS files, including the app.js, because we are not referencing the app.ts file in HTML, because the Typescript  compiler converts the code in to java script, we have to refer that file 

In this sample i am using the Bootstrap also for a good looking UI. Here in this html there is no change  as usual we can declare the app module and controller . Variable can be accessed using the $scope map with the tag

<!DOCTYPE html>
<html>
<head>
    <title></title>
	<meta charset="utf-8" />
    <link rel="stylesheet" href="Content/bootstrap-theme.css" type="text/css" />
    <link rel="stylesheet" href="Content/bootstrap.css" type="text/css" />

    <script type="text/javascript" src="scripts/angular.js"></script>
    <script type="text/javascript" src="scripts/angular-route.js"></script>
    <script type="text/javascript" src="scripts/jquery-1.9.1.js"></script>
    <script type="text/javascript" src="scripts/bootstrap.js"></script>
    <script type="text/javascript" src="app/app.js"></script>

</head>
<body ng-app="app">

    <div class="row" style="padding:20px"></div>
    <div class="row">
        <div class="col-lg-2"></div>
        <div ng-controller="MainController" class="panel panel-info col-lg-4">
            <div class="panel-heading">
                {{title}}
            </div>
            <div class="breadcrumb">{{name}}</div>
            <div class="panel-body">
                <div class="row">
                    <div class="col-lg-8"></div>
                    <div class="col-lg-3">
                        <input value="Get Employees" type="button" 
                               class="btn btn-primary" 
                               ng-click="getEmployees()" />
                    </div>
                </div>
                <div class="row" style="margin-top:10px">
                    <ul class="list-group">
                        <li class="list-group-item list-group-item-info" 
                            ng-repeat="emp in Employees">
                            <div class="text-center text-muted row">
                                <span class="col-md-3">{{emp.id}}</span>  
                                <span class="col-md-5">{{emp.name}}</span>
                                <span class="col-md-4">{{emp.address}}</span>
                            </div>
                        </li>
                    </ul>
                </div>
                </div>
        </div>
    </div>
</body>
</html>

Full Source Code app.ts (Typescript)

/// <reference path="../scripts/typings/angularjs/angular.d.ts" />
/// <reference path="../scripts/typings/angularjs/angular-route.d.ts" />

module DotnetVisio.Model {
    export class Employee {
        id: number;
        name: string;
        address: string;
    }
}

module DotnetVisio.Interfaces {
    export interface IMainScope extends ng.IScope {
        name: string;
        title: string;
        Employees: Array<Model.Employee>;
        getEmployees(): void;
    }
}

module DotnetVisio.Controllers {

    export class MainController{
        private $scope: Interfaces.IMainScope;

        constructor($scope: Interfaces.IMainScope) {
            var ViewModel = this;
            ViewModel.$scope = $scope;
            ViewModel.$scope.title = "Angular Sample";
            ViewModel.$scope.name = "Employees";
            ViewModel.InitMethods();
        }

        private InitMethods(): void {
            var ViewModel = this;

            ViewModel.$scope.Employees = [];

            ViewModel.$scope.getEmployees = function () {

                ViewModel.$scope.Employees =  <Model.Employee[]>[
                    <Model.Employee>{ id: 1, name: "Rajesh", address: "Chennai" },
                    <Model.Employee>{ id: 2, name: "Suresh", address: "California" },
                    <Model.Employee>{ id: 3, name: "Ramu", address: "Pune" },
                    <Model.Employee>{ id: 4, name: "Shiny", address: "London" }
                ];

            }
            
        }
        
        static $inject = ['$scope'];
    }  
}

module DotnetVisio.Module {

    var app = angular.module('app', []);
    app.controller('MainController', Controllers.MainController);    

}



Full source code generated by Typescript as app.js
/// <reference path="../scripts/typings/angularjs/angular.d.ts" />
/// <reference path="../scripts/typings/angularjs/angular-route.d.ts" />
var DotnetVisio;
(function (DotnetVisio) {
    var Model;
    (function (Model) {
        var Employee = (function () {
            function Employee() {
            }
            return Employee;
        })();
        Model.Employee = Employee;
    })(Model = DotnetVisio.Model || (DotnetVisio.Model = {}));
})(DotnetVisio || (DotnetVisio = {}));
var DotnetVisio;
(function (DotnetVisio) {
    var Controllers;
    (function (Controllers) {
        var MainController = (function () {
            function MainController($scope) {
                var ViewModel = this;
                ViewModel.$scope = $scope;
                ViewModel.$scope.title = "Angular Sample";
                ViewModel.$scope.name = "Employees";
                ViewModel.InitMethods();
            }
            MainController.prototype.InitMethods = function () {
                var ViewModel = this;
                ViewModel.$scope.Employees = [];
                ViewModel.$scope.getEmployees = function () {
                    ViewModel.$scope.Employees = [
                        { id: 1, name: "Rajesh", address: "Chennai" },
                        { id: 2, name: "Suresh", address: "California" },
                        { id: 3, name: "Ramu", address: "Pune" },
                        { id: 4, name: "Shiny", address: "London" }
                    ];
                };
            };
            MainController.$inject = ['$scope'];
            return MainController;
        })();
        Controllers.MainController = MainController;
    })(Controllers = DotnetVisio.Controllers || (DotnetVisio.Controllers = {}));
})(DotnetVisio || (DotnetVisio = {}));
var DotnetVisio;
(function (DotnetVisio) {
    var Module;
    (function (Module) {
        var app = angular.module('app', []);
        app.controller('MainController', DotnetVisio.Controllers.MainController);
    })(Module = DotnetVisio.Module || (DotnetVisio.Module = {}));
})(DotnetVisio || (DotnetVisio = {}));



Output:








From this post you can see how to create a angular js applications using the Typescript. along with creation of module, controller in typescript 

No comments:

Post a Comment