Friday, August 28, 2015

This little thing called this

While learning the Basic Authentication on node express, I encountered the need to learn javascript more. One thing I learned today is the use of .bind function of javascript. I seen it being used most on javascript UI frameworks, I didn't bother to learn what's the use of that bind function, until today.

On Basic Authentication of node express, I need to pass an extra parameter to node express callback, that parameter is role. That role parameter is akin to Authorize attribute of ASP.NET MVC.

Here's a rough signature of node express callback:

interface Func {
    (random: number, basicAuthUser: string) : boolean;
}


function doSomething(...actions: Func[]) : void {
    
    var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication    
    
    for(var i = 0; i < actions.length; ++i) {
        var a = actions[i];
        var okToContinue = a(Math.random() * 100, basicAuthUser);
        if (!okToContinue) 
            break;
    }
}

console.log('');
console.log('without authorization');
doSomething(
    (i,u) => { console.log('Alpha ' + i); return true; },
    (i,u) => { console.log('Beta ' + i); return true; }
    );


Then I think, authentication and authorization role mechanism could be slotted on the first parameter of the array. But how would I pass an extra parameter on the callback? Then an enlightenment from C# came. On C# object, the properties can be accessed even if the method reference is passed to callback. The solution could be written in C# like the following:


Live Code: https://dotnetfiddle.net/tSenYK
using System;
using System.Linq;
                    
public class Program
{
    public static void Main()
    {
        Console.WriteLine("Without authorization:");
        DoSomething(            
            (i,u) => { Console.WriteLine("Alpha " + i); return true; },
            (i,u) => { Console.WriteLine("Beta " + i); return true; }            
            );    
                
        Console.WriteLine();
        Console.WriteLine("Rockstar activity:");
        DoSomething(
            new Authorizer("rockstar").ActionToDo, // just pass the reference of method
            (i,u) => { Console.WriteLine("Alpha " + i); return true; },
            (i,u) => { Console.WriteLine("Beta " + i); return true; }            
            );                        
        
        Console.WriteLine();
        Console.WriteLine("Guest activity:");        
        DoSomething(
            new Authorizer("guest").ActionToDo,
            (i,u) => { Console.WriteLine("Alpha " + i); return true; },
            (i,u) => { Console.WriteLine("Beta " + i); return true; }            
        );    
    }
    
    
    // third-party framework. cannot change the signature
    public static void DoSomething(params Func<int, string, bool>[] actions)
    {
        var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication        
        for(int i = 0; i < actions.Length; ++i)
        {
            var a = actions[i];
            bool okToContinue = a(new Random().Next(10), basicAuthUser);
            if (!okToContinue)
                break;
        }
        
    }
    

}



class Authorizer
{
    public string RoleAllowed { get; set; }
    
    public Authorizer(string roleAllowed)
    {
        this.RoleAllowed = roleAllowed;
    }
    
    string GetRole(string basicAuthUser)
    {
        return "rockstar"; // davegrohl's role fetched from database
    }
    
    public bool ActionToDo(int i, string basicAuthUser) 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        var role = this.GetRole(basicAuthUser);
        
        
        
        return role == this.RoleAllowed;    
    }
}

Output:
Without authorization:
Alpha 4
Beta 4

Rockstar activity:
Alpha 4
Beta 4

Guest activity:


So I just need write the equivalent in TypeScript/JavaScript:

Live Code at TypeScriptLang


class Authorizer
{
    roleAllowed : string;
    
    constructor(roleAllowed: string)
    {
        this.roleAllowed = roleAllowed;
    }
    
        
    private getRole(basicAuthUser: string) : string {
        return "rockstar"; // davegrohl's role fetched from database
    }
    
    actionToDo(i: number, basicAuthUser: string) : boolean 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        
        var role = this.getRole(basicAuthUser); // davegrohl's role fetched from database
                
        return role === this.roleAllowed;    
    }
}



    


interface Func {
    (random: number, basicAuthUser: string) : boolean;
}


function doSomething(...actions: Func[]) : void {
    
    var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication    
    
    for(var i = 0; i < actions.length; ++i) {
        var a = actions[i];
        var okToContinue = a(Math.random() * 100, basicAuthUser);
        if (!okToContinue) 
            break;
    }
}

console.log('');
console.log('without authorization');
doSomething(
    (i,u) => { console.log('Alpha ' + i); return true; },
    (i,u) => { console.log('Beta ' + i); return true; }
    );
    


console.log('');
console.log("Rockstar activity:");
doSomething(
    new Authorizer("rockstar").actionToDo,
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
    );                        


console.log('');
console.log("Guest activity:");        
doSomething(
    new Authorizer("guest").actionToDo,
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
);    


However, it didn't work. The this object looks like it's not an instance af Authorizer class. The error says:





Then I add a console.log of the this object.
actionToDo(i: number, basicAuthUser: string) : boolean 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        
        console.log(this);
        
        var role = this.getRole(basicAuthUser); // davegrohl's role fetched from database
                
        return role === this.roleAllowed;    
    }


Here's the output, oops it looks like the this object is not carried when passing the reference of the method to callbacks.



To make the long story short, the this object is not included when accessing the reference of the method. Not similar to C#

The solution is to bind the this object before passing the reference of the method to callback.

Correct:

Live Code at TypeScriptLang

class Authorizer
{
    roleAllowed : string;
    
    constructor(roleAllowed: string)
    {
        this.roleAllowed = roleAllowed;
    }
    
    getBindedActionToDo() : Func {
        return this.actionToDo.bind(this);
    }
    
    private getRole(basicAuthUser: string) : string {
        return "rockstar"; // davegrohl's role fetched from database
    }
    
    actionToDo(i: number, basicAuthUser: string) : boolean 
    {
        // Database operation here.
        // Get the role of basicAuthUser
        
        console.log(this);
        
        var role = this.getRole(basicAuthUser); // davegrohl's role fetched from database
                
        return role === this.roleAllowed;    
    }
}



interface Func {
    (random: number, basicAuthUser: string) : boolean;
}


function doSomething(...actions: Func[]) : void {
    
    var basicAuthUser = "davegrohl"; // obtained from browser's Basic Authentication    
    
    for(var i = 0; i < actions.length; ++i) {
        var a = actions[i];
        var okToContinue = a(Math.random() * 100, basicAuthUser);
        if (!okToContinue) 
            break;
    }
}

console.log('');
console.log('without authorization');
doSomething(
    (i,u) => { console.log('Alpha ' + i); return true; },
    (i,u) => { console.log('Beta ' + i); return true; }
    );
    


console.log('');
console.log("Rockstar activity:");
doSomething(
    new Authorizer("rockstar").getBindedActionToDo(),
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
    );                        


console.log('');
console.log("Guest activity:");        
doSomething(
    new Authorizer("guest").getBindedActionToDo(),
    (i,u) => { console.log("Alpha " + i); return true; },
    (i,u) => { console.log("Beta " + i); return true; }            
);    


Output:





Happy Coding!

Testing an AMD POJO Angular Controller

One of the nice things of Controllers in ASP.NET MVC is they are easy to test, just new the controller and you are good to go.

One of the nice things with new Angular removing reliance on $scope is we can now test controllers just by newing them, we don't need to worry where to get the $scope variable being passed to it. Our controller becomes very POJO, very easy to test.


An example of POJO controller.

///<reference path="../../../typings/requirejs/require.d.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>
///<reference path="../../../shared/ViewValue/Header.ts"/>
///<reference path="../../../shared/Domain/Product.ts"/>


module App.ProductForSale {

    export class Controller {

        product : Domain.Product;

        percentDiscount: number;

        get discountedPrice() : number {

            return this.product.price * (1 - this.percentDiscount);
        }

        constructor(header: ViewValue.Header) {

            header.title = "Product for sale";

            this.product = new Domain.Product();
        }
    }
}


define(require => {

    var mod : angular.IModule = require('theMainModule');
    require('/shared/Domain/Product.js');

    mod["registerController"]('ProductForSaleController',['singletonHeader', App.ProductForSale.Controller]);

});


There's just one minor problem when testing the controller above. It's an AMD controller, to test it we should be able to ignore the define statement in it.


The easiest way to disable it is to monkey-patch the define function by changing it to something else. An example. Name this test setup as _must-be-runned-first.ts:


if (window["def"] == undefined) {
    window["def"] = window["define"];

    window["define"] = function(depArray : string[], c: any) {
        console.log('define intercepted');
        console.log(depArray);
    };
}



function doTest(test) {
    var def = window["def"];

    def(test);
}

doTest just wrap the test so tests uses the original define, other defines just got redirected.


Here's a sample test:

///<reference path="../typings/jasmine/jasmine.d.ts"/>
///<reference path="../typings/requirejs/require.d.ts"/>
///<reference path="_must-be-runned-first.ts"/>

doTest(require => {


    describe("Board Controller", () => {
        require('/base/public/app-dir/ProductForSale/Controller.js');
        require('/base/shared/ViewValue/Header.js');


        var h = new ViewValue.Header();

        it("computes discount", () => {

            var b = new App.ProductForSale.Controller(h);
            b.product.price = 50;
            b.percentDiscount = 0.10;
            var discountedPrice = 45;

            expect(b.discountedPrice).toEqual(discountedPrice);

        });
    });
});


By redefining the window["define"] to something else, requirejs won't complain of script error on theMainModule as it is not available when doing tests on controller.



Add test-main.js on files array of karma.conf

module.exports = function(config) {
    config.set({

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',


        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine', 'requirejs'],


        // list of files / patterns to load in the browser
        files: [
            'test-main.js',
            {pattern: 'shared/**/*.js', included: false},
            {pattern: 'public/**/*.js', included: false},
            {pattern: 'tests/*.js', included: false}
        ]
    });
}



Then on test-main.js, add the _must-be-runned-first.js as the first file to be dynamically-loaded, remove the .js extension when adding it to allTestFiles array.


var allTestFiles = [];

var TEST_REGEXP = /(spec|test)\.js$/i;

allTestFiles.push('tests/_must-be-runned-first');

// Get a list of all the test files to include
Object.keys(window.__karma__.files).forEach(function(file) {
    if (TEST_REGEXP.test(file)) {
        // Normalize paths to RequireJS module names.
        // If you require sub-dependencies of test files to be loaded as-is (requiring file extension)
        // then do not normalize the paths
        var normalizedTestModule = file.replace(/^\/base\/|\.js$/g, '');

        allTestFiles.push(normalizedTestModule);
    }
});


console.log(allTestFiles);

require.config({
    // Karma serves files under /base, which is the basePath from your config file
    baseUrl: '/base',


    // dynamically load all test files
    deps: allTestFiles,

    // we have to kickoff jasmine, as it is asynchronous
    callback: window.__karma__.start
});



Complete Code: https://github.com/MichaelBuen/PlayNodeTypescriptUirouterCouchpotato/tree/master/public


Happy Coding!

Tuesday, August 25, 2015

Angular Service and Factory are just the same

That is, the values of service/factory values being passed to controllers are singletons.

The only difference between the two; with service it's Angular's job to do the new'ing, with factory it's the responsibility of your factory's callback to do the new'ing. Despite the name factory, don't be confused that it gets called every time it is needed by controllers, that it can make a new instance every time it is called; in fact, the factory's callback is only called once by Angular, effectively its result is also cached just like service. Here are the screenshots showing how many times the service and factory are being called.


Service:


Factory:



As shown on screenshot, Domain.Product is new'd only once on service, even the factory is just called once. Hence the values being passed to controllers, be it from service or from factory, have just the same instance, are effectively singletons.


Imagine service is implemented as:
function service(nameHere, c) {
    cache[nameHere] = new c(); // new'd once only.
} 

Imagine factory is implemented as:
function factory(nameHere, c) {
    cache[nameHere] = c(); // called once only.
}


As for which one is used more often or should be used more often. If factory is called every time it is being needed on controller, it will fit the name factory more . But alas, factory is just called once, effectively returning singletons only, it's better to use service if all you need is singleton.


You can even use service if you want to make a real factory. Of course, you can also use factory if you want to make a real factory :)


/TheApp.ts:
///<reference path="../typings/requirejs/require.d.ts"/>
///<reference path="../typings/angularjs/angular.d.ts"/>

///<reference path="../shared/Domain/Product.ts"/>



define(['angular', 'angularUIRouter', 'angularResource', 'couchPotato' ], function(angular, angularUIRouter, angularResource, couchPotato) {

    var app = angular.module('niceApp',['ui.router','ngResource','scs.couch-potato']);


    var useService : boolean = true;

    if (useService)
        app.service('domainProduct', Domain.Product);
    else
        app.factory('domainProduct', () => {
            console.log('Factory');
            return new Domain.Product();
        });

    couchPotato.configureApp(app); // this dynamically adds registerProvider on angular module niceApp

    return app;

});

/shared/Domain/Product.ts:
module Domain {

    export class Product {
    
        name : string;
        yearModel : number;

        constructor() {
            this.name = "Initial Value";
            this.yearModel = 1900;

            console.log('Product Constructor');
        }
    }
}

/app-dir/Product/Controller.ts
//<reference path="../../../typings/requirejs/require.d.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>
///<reference path="../../../shared/Domain/Product.ts"/>


class Controller {

    sampleMessage : string;

    domainProduct : Domain.Product;

    constructor($scope : angular.IScope, domainProduct) {

        console.log("Product's Controller: User of factory/services");
        
        this.domainProduct = domainProduct;

    }
    
}

define(['theApp'], function (app) {
    app.registerController('ProductController',['$scope', 'domainProduct', Controller]);
});

/app-dir/Product/SidebarController.ts
///<reference path="../../../typings/requirejs/require.d.ts"/>
///<reference path="../../../typings/angularjs/angular.d.ts"/>
///<reference path="../../../shared/Domain/Product.ts"/>

class Controller {

    sampleMessage : string;

    domainProduct : Domain.Product;

    constructor($scope : angular.IScope, domainProduct) {
    
        console.log("Product's Sidebar Controller: User of factory/services");

        this.domainProduct = domainProduct;
    }
}


define(['theApp'], function (app) {
    app.registerController('ProductSidebarController',['$scope', 'domainProduct', Controller]);
});

Saturday, August 22, 2015

Conflict between NodeJS's require and RequireJS's require TypeScript definitions

At the time of this writing, if you wanted to use TypeScript's umd (Universal Module Definition), you'll get an error between NodeJS's require and RequireJS's require TypeScript definitions.




A temporary solution to that is to disable the RequireJS's require, delete the ambient declaration for requirejs's require.

/typings/requirejs/require.d.ts
// Ambient declarations for 'require' and 'define'
declare var requirejs: Require;
// declare var require: Require // Delete or uncomment this
declare var define: RequireDefine;


This client-side config.ts won't work anymore:
requirejs.config({
    paths: {
        "jquery": "/jquery/dist/jquery"
    }
});
 
require(['app']); // this won't work


To make that work, access the client-side require via window object.
requirejs.config({
    paths: {
        "jquery": "/jquery/dist/jquery"
    }
});
 
var need : Require = window["require"];
need(['app']);

Friday, August 21, 2015

Sharing TypeScript classes between front-end and web server code

The beauty of using javascript is it can now run on server-side via nodejs. Using javascript on both client-side and server-side facilitates code-sharing much easier.

Prerequisite: use UMD.
{
 "compilerOptions": {
  "target": "ES5",
  "module": "umd",
  "sourceMap": true
 } 
}

This is a class with validation logic that can be used on front-end:

/shared/Domain/Person.ts
module Domain {
        
    export class Person {
        name : string;
        age : number;
        
        validate() : string[] {
            var validations : string[] = [];
            
            if (this.age < 0 || this.age == undefined || this.age == null)
                validations.push('Age must be equal or more than zero');
                
            return validations;    
        }
        
    }
}




The above can be used directly on front-end app:

/public/app/Person/Controller.ts
class Controller {
    
    name : string = 'Linus T';
    
    person  = new Domain.Person();
    
    validationMessages : string[];
        
    constructor() {
        this.person.name = 'Nice fellow';
        this.person.age = -39;     
    } 
    
    save() : void {
                
        this.validationMessages = this.person.validate();
                
    }
                
}

angular.module('TheApp', []).controller('Controller', Controller);


The javascript on the browser don't have a problem looking for the reference of Domain.Person class, as the class is referenced from the view.
<script src='/angular/angular.min.js'></script>
<script src='/shared/Domain/Person.js'></script>
<script src='Controller.js'></script>

<div ng-app="TheApp" ng-controller="Controller as c">
    {{c.name}}
    
    <p>
        Person: {{c.person}}
    </p>    
    
    <p>
        {{c.validationMessages}}
    </p>
    
    <button ng-click="c.save()">Save</button>
    
</div>


However, you cannot import an internal module directly from a nodejs app. TypeScript complains that a module is not a module (external module that is).



In order to use a module in nodejs, the module must be an external one. To convert an internal module to external module, just export the module Domain by attaching export = Domain at the end of code.


/shared/Domain/Person.ts
module Domain {
        
    export class Person {
        name : string;
        age : number;
        
        validate() : string[] {
            var validations : string[] = [];
            
            if (this.age < 0 || this.age == undefined || this.age == null)
                validations.push('Age must be equals or more than zero');
                
            return validations;    
        }
        
    }
}

export = Domain;

Doing the above, this shall work.

/app.ts
import domain = require('./shared/Domain/Person');

app.post('/api/person', (req,res) => {
    
    var person = new domain.Person(); // intellisense works
    extend(person, req.body);
            
    var messages = person.validate();  
  
      if (messages.length > 0)
        res.status(400).json(messages);
    else
        res.send('OK'); 



And also, another problem is once you convert an internal module to external module, the module can't be recognized as an internal one anymore. Hence this front-end code will get an error:




Fortunately, someone was able to crack that problem. Another dev make it clearer. There's another dev who made a post on his enlightenment on the internals of require function.


To cut to the chase, keep the module as internal, then manually register modules to exports variable (the global variable being used by CommonJS's require).


/shared/Domain/Person.ts:
module Domain {
        
    export class Person {
        name : string;
        age : number;
        
        // we can use this logic on front-end, e.g., Angular.
        // and we can also re-use this logic on back-end, e.g., NodeJS's REST API 
        validate() : string[] {
            var validations : string[] = [];
            
            if (this.age < 0 || this.age == undefined || this.age == null)
                validations.push('Age must be equals or more than zero');
                
            return validations;    
        }
        
    }
}

declare var exports: any;
if (typeof exports != 'undefined') {
    exports.DomainPerson = Domain.Person;


Organize the classes to their own file, let's add another one. The exports code have to be repeated on each class.
module Domain {
    export class Country {
        name : string;
    }
}

declare var exports: any;
if (typeof exports != 'undefined') {
    exports.DomainCountry = Domain.Country;
}


Then on external module-using code, we will not use TypeScript's import functionality, so the TypeScript compiler will not flag the module as not a module. To wit:


class ExternalizedDomain {
    static Person : typeof Domain.Person = require('./shared/Domain/Person').DomainPerson;
    static Country : typeof Domain.Country = require('./shared/Domain/Country').DomainCountry;
}


The suffixes .DomainPerson and .DomainCountry are the name of the exported classes from modules that were stored in exports variable, which in turn is returned by the require function. As the module is not imported by TypeScript, the modules would have no associated types, we can re-introduce the imported modules as strongly-typed classes by using TypeScript's typeof operator.

Following is the REST API code that re-uses the same class(with validation logic) being used by front-end. Using nodejs, we can keep our front-end code and REST API code DRY.


import express = require('express');

import path = require('path');

import bodyParser = require('body-parser'); 

import extend = require('extend');


class ExternalizedDomain {
    static Person : typeof Domain.Person = require('./shared/Domain/Person').DomainPerson;
    static Country : typeof Domain.Country = require('./shared/Domain/Country').DomainCountry;
}


var app = express();


app.get('/', (req,res) => res.send('Hello Lambda World!'));

    var server = app.listen(3000, function () {
    var host = server.address().address;
    var port = server.address().port;

    console.log('Example app listening at http://%s:%s', host, port);
    
});



app.use('/', express.static( path.join(__dirname, 'public'), { extensions: ['html'] })); // if entered a url without an extension, attach html
app.use('/angular', express.static( path.join(__dirname, 'node_modules', 'angular') )); 

app.use('/shared', express.static( path.join(__dirname, 'shared') )); 

app.use(bodyParser.json());
app.post('/api/person', (req,res) => {
   
   
    var person = new ExternalizedDomain.Person();
    extend(person, req.body);
            
    var messages = person.validate();  
   
    if (messages.length > 0)
        res.status(400).json(messages); // 400 is http status for bad request
    else
        res.send('OK'); 
    
});


The technique above works on modules too:
module Domain.Calculator {

    export function multiply(multiplicand: number, multiplier: number): number {

        return multiplicand * multiplier ;
    }

    export function divide(dividend: number, divisor: number): number {

        return null;
    }
}

declare var exports: any;
if (typeof exports != 'undefined') {
    exports.Calculator = Domain.Calculator;
}

To use:

class ExternalizedDomain {
    static Calculator : typeof Domain.Calculator = require('../shared/Domain/Calculator').Calculator;
}

describe("multiplication", () => {
    it("should multiply 2 and 3", () => {
        var product = ExternalizedDomain.Calculator.multiply(2,3);
        expect(product).toEqual(6);
    });
});


TypeScript works perfect on Visual Studio Code. Intellisense works as expected:



WebStorm can't intelligently work on the language:




Complete code, done on Visual Studio Code: https://github.com/MichaelBuen/PlaySharedTypeScriptClasses


Happy Coding!

Monday, July 20, 2015

Using TypeScript on Express

Prerequisites:
  • Install Node.js
    • To see installed version
      $ node -v
  • Install Visual Studio Code
    • To alias Visual Studio Code to code, just add the following to your ~/.bash_profile
      code () {
          VSCODE_CWD="$PWD" open -n -b "com.microsoft.VSCode" --args $*
      }
      

Express using plain vanilla JavaScript:


Express using TypeScript

  • Prerequisites
    • Install TypeScript compiler. Requires sudo.
      • $ sudo npm install -g typescript 
      • To see installed TypeScript version:
        • $ tsc -v
      • Install TypeScript Definition manager. Requires sudo.
        • $ sudo npm install -g tsd
        • To see installed TypeScript Definition manager's version:
          • $ tsd -V
  • TypeScript configuration
    • Create a new file then save(so intellisense will kick in if you want to manually type the content below) blank tsconfig.json file under MYAPP folder (the folder from Express installation).  Content:
    •  
      {
       "compilerOptions": {
        "target": "ES5",
        "module": "commonjs",
        "sourceMap": true
       }
      }
    • Build by pressing Command+Shift+B
      • You'll see message: No task runner configured. Then click Configure Task Runner.
        • Remove this entry:
          • "args": ["HelloWorld.ts"],
  • Converting JavaScript to TypeScript
    • Rename app.js to app.ts. As soon you as you renamed it to ts file, Visual Studio Code will show a message that the require function is not found. To fix, change the var express to import express
      • As soon as you change var express to import express, TypeScript will show another error that says it cannot find the external module 'express'.
        • To fix that, install TypeScript definition for express
          • $ tsd install express --save
    • Build by pressing Command+Shift+B. The error pertaining to module express shall be gone. However, at the time of this writing, you'll see four errors related to node.d.ts use of ES6 data structure, DataView, Map, Set, WeakMap, we will fix these errors later.
    • Another thing to note, as soon you edit your code, you'll see again the error pertaining to missing module express. You can fix that by building the project, however as soon as you edit your code again, the errors will be back. To make the error really disappear, just quit Visual Studio Code then open your project again. This is just a glitch in Visual Studio Code.
    • You can now test the intellisense goodness TypeScript and Visual Studio Code brings. For a start, type app then press the dot, all the available methods of express will be shown.
    • Test a TypeScript syntax, lambda for example:
      • Change this:
      • app.get('/', function (req, res) {
            res.send('Hello World!');
        });
        
      • Into this:
      • app.get('/', (req, res) => res.send('Hello World!'));
    • Build by pressing Command+Shift+B again, then relaunch node app.js from the terminal; not app.ts. Refresh the browser, you'll see Hello Lambda World!
    • At the time of this writing, the typescript definition for node has four errors, the errors is related to ECMAScript 6's data structures (DataView, Map, Set, WeakMap), the easiest solution is get the previous TypeScript definition for node. Solution found on stackoverflow.
      • Open tsd.json, change the commit id of node.d.ts
      • "node/node.d.ts": {
           "commit": "7bab855ae33d79e86da1eb6c73a7f7eab2676ddb"
        }
        
      • Delete the typings directory, and re-install the TypeScript definitions
        • $ tsd reinstall -s
    • Build by pressing Command+Shift+B. The four errors shall be gone.
    • However, due to Visual Studio Code glitch, as soon as you edit your code, it will show back the errors. You can make those errors disappear, just build by pressing Command+Shift+B, however that is temporary, as soon as you edit your code, the errors will be back. To make it disappear permanently, just quit and re-open Visual Studio Code. One thing I noticed, even we don't quit and re-open Visual Studio Code, the errors will appear permanently just by waiting for a minute. It's better to quit and re-open Visual Studio Code :-)


    app.ts
    import express = require('express');
    var app = express();
    
    app.get('/', (req, res) => res.send('Hello Lambda World!'));
    
    
    var server = app.listen(3000, function () {
      var host = server.address().address;
      var port = server.address().port;
    
      console.log('Example app listening at http://%s:%s', host, port);
    });
    


    Happy Coding!

    Saturday, November 1, 2014

    Angular Ajax Combobox

    Angular Ajax Combobox component

    Features:
    • On-demand loading of list
    • Paged list
    • Can use page up / page down shortcut when navigating the list
    • Can type on textbox anytime even when the dropdown list is displayed
    • Can use mouse scroll on the popup list
    • Uses AngularJS 1.3 ng-model debounce functionality to prevent fast typist from overwhelming the network
    • Keyboard shortcut to popup the list uses the conventional shortcut, Alt+Down, or F4
    • Aside from next page / previous page buttons, it has fast forward and fast reverse button, it partition the list by 100 instead of the usual ten for paging. Say we have 5,000 rows, a total of 500 pages, so from first page when we click the fast forward button it brings us to page 51
    • Can manually assign both ID/Code and Text for the combobox, by using ng-model and user-input attributes respectively. Think edit
    • When pressing escape key, it reverts back the old value. Likewise when pressing tab, yet the user didn't select an item, the combobox will revert to old ID/Code and Text values
    • Developer still has control on the requested ajax url's parameter names, and also with the result's list and total's property names. The component doesn't impose any names for the ajax's url parameter names and response property names
    • ng-change event, things like cascading combobox is possible
    • Combobox width can be overriden
    • The popup's width has the same width as the combobox
    • Uses bootstrap for the design
    • No jQuery
    • Page Size


    Front-end code:
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
     
        <script src="Scripts/angular.min.js"></script>
        <script src="Scripts/angular-resource.min.js"></script>
     
        <link rel="stylesheet" href="Content/bootstrap.min.css" />
     
        <link rel="stylesheet" href="Content/kel.ui.css" />
        <script src="Scripts/kel.ui.js"></script>
     
        <script src="Scripts/app.js"></script>
     
     
    </head>
    <body ng-app="TheApp" ng-controller="TheController as c">
     
     
        <h3>Angular Ajax Combobox Demo</h3>
     
     
        <div>PersonId chosen: {{c.personId}}</div>
        <br />
        <div style="float: left">Person name:&nbsp;</div>
        <kel-ajax-combobox ng-model="c.personId"
                           user-input="c.personName"
                           result-getter="c.resultGetter"
                           result-list="c.resultList"
                           result-total-rows="c.resultTotalRows"
                           selected-value="'id'"
                           selected-text="'fullName'"
             <!--width="'450px'"-->
             <!--page-size="20"-->
        ></kel-ajax-combobox>
     
    </body>
    </html>
    
    Output:
    app.js:
    var app = angular.module('TheApp', ['ngResource', 'kel.ui']);
    
    
    app.controller('TheController', ['$http', '$resource', function($http, $resource) {
        var vm = this;
    
        vm.personId = 5500;
        vm.personName = 'Aaron Butler';
    
        vm.resultList = [];
        vm.resultTotalRows = 0;
    
        var dataRest = $resource('http://localhost:63692/api/AdventureWorksPeople');
    
        vm.resultGetter = function(e) {      
             return dataRest.get({ userInput : e.userInput, pageNumber : e.pageNumber, pageSize : e.pageSize }, function(result) {
                 vm.resultList = result.persons;
                 vm.resultTotalRows = result.totalRows;
             });
        };
    
        //// This now works:
    
        //vm.resultGetter = function(e) {
        //        return dataRest.get({ userInput : e.userInput, pageNumber : e.pageNumber, pageSize : e.pageSize }).$promise.then(function(result) {
        //            vm.resultList = result.persons;
        //            vm.resultTotalRows = result.totalRows;
        //        });
        //};
    
    }]);
    


    Sample application layer code:

    using System.Web.Http;
    
    using Dapper;
    
    using System.Web.Http;
    using System.Collections.Generic;
    
    using ReadyAspNetWebApiCors.Dtos;
    
    
    namespace ReadyAspNetWebApiCors.Controllers
    {
        
        [System.Web.Http.Cors.EnableCors(origins: "*", headers: "*", methods: "*")]
        public class AdventureWorksPeopleController : ApiController
        {
            // GET api/<controller>
            public PagedDtoResult Get([FromUri] PagingDto dto)
            {
                int pageLimit = 10;
    
                using (var con = new System.Data.SqlClient.SqlConnection(
                                     "Server=.; Database=AdventureWorks2012; Trusted_Connection=true;"))
                {
                    var persons = con.Query<PersonDto>(
                        @"with x as (
                            select Id = BusinessEntityId, FullName = FirstName + ' ' + LastName 
                            from Person.Person 
                        )
                        select * 
                        from x
                        where FullName like @filterName + '%' or @filterName = ''
                        order by FullName 
                        offset @offset rows fetch next @pageSize rows only", 
                            new { filterName = dto.UserInput ?? "", 
                                  offset = pageLimit * (dto.PageNumber-1), pageSize = dto.PageSize });
    
    
                    var totalRows = con.ExecuteScalar<int>(
                        @"with x as (
                            select FullName = FirstName + ' ' + LastName 
                            from Person.Person 
                        )
                        select count(*)
                        from x
                        where FullName like @filterName + '%' or @filterName = ''", 
                            new { filterName = dto.UserInput ?? "" });
    
    
                    return new PagedDtoResult
                    {
                        Persons   = persons,
                        TotalRows = totalRows
                        
                    };
                }
            }
        
        }
    }
    
    
    
    
    namespace ReadyAspNetWebApiCors.Dtos
    {
        public class PersonDto
        {
            public int    Id        { get; set; }
            public string FullName  { get; set; }
        }
    }
    
    namespace ReadyAspNetWebApiCors.Dtos
    {
        public class PagingDto
        {
            public string UserInput { get; set; }        
            public int    PageNumber { get; set; }
            public int    PageSize   { get; set; }
        }
    }   
    
    
    
    
    
    namespace ReadyAspNetWebApiCors.Dtos
    {
        public class PagedDtoResult
        {
            public int TotalRows { get; set; }
            public IEnumerable<PersonDto> Persons { get; set; }
        }
    }
    
    
    
    // Add this on WebApiConfig.Register
    
    config.EnableCors();
    
    
    var formatters = GlobalConfiguration.Configuration.Formatters;
    var jsonFormatter = formatters.JsonFormatter;
    var settings = jsonFormatter.SerializerSettings;
    settings.Formatting = Newtonsoft.Json.Formatting.Indented;
    settings.ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver();
    
    


    Download the library from: http://www.nuget.org/packages/kel.angular.ajax.combobox/

    Git: https://github.com/MichaelBuen/AngularAjaxComboBox


    Happy Coding!