Monday, October 24, 2016

React-Navite - Introduction

React Native is one of the very few frameworks that has changed the way mobile applications can be built. Notice how I said mobile applications and not iOS or Android applications or for that matter mobile or tablet devices. React native applies to both. Now you think ahhhh, I have heard this before, we have looked at a lot of frameworks/packages like this before - PhoneGap, Titanium, Kony, Xamarin and so many others. If you think React-Native is one among them you are thoroughly mistaken.

What we look for in mobile applications

There is always a native language to build applications for smart devices and in the case of iOS, there is more than one. Why even concern about anything more to build a native application. What's special about React-Native and why should we care about it. That's a great question to start with.

Developing applications for smart devices is no longer simple anymore. It's not some 5 forms and a list application pattern. People are building CRM and ERP applications for mobile. Today, mobile solutions have changed from antiquated or even an extension from web into a full fledged solutions. In some cases mobile applications are the only go, they don't even have web counter-parts and future looks more like that. I have personally built applications that have more than 100 forms and at least about 40 lists. I am not going got brag about my mobile development experience here, but what I am trying to say is, it is a complex world out there. Applications are gynormous. Maintenance is a major  head-ache. In addition to our work on module, size complexities you have to think about several other factors and that includes


  1. How intuitive is the UI
  2. Support for mobile analytics 
  3. How Keyboard UI is presented and their customizations
  4. Application behavior in different orientations
  5. Graphics/Animation support inline with the application (I am not talking about those fancy animations that annoy users, so to say, but simple animations), 
  6. Access to native objects/applications to build a complete application
  7. Access to local storage, where ever possible. 
  8. Security of data, network operations
These are just a few of them, but you see where I am going

Benefits of building application from common frameworks


We may talk about couple more choices, but I think, if we can have a custom framework that allows us to do all of the above in one seamless form, we all can agree that, it's a great way to get started. And here are some reasons


  1. Code sharability (Even if it is a copy-paste code between iOS & Android, although there are nice design-patterns to handle such cases)
  2. Consistent design patterns between different devices, frameworks
  3. Similar and consistent approach for development, process and maintenance tools
  4. Better planning on tool investment like CI, code analysis etc
  5. Better network handling

Can React-Native help?


We talked about benefits of using a consistent programming language, but such a thing seems to be in an utopian world. Do we have anything closer to reality? The answer is YES and that's where React-Native comes in. This framework from Facebook, allows you to write your application in ES6. Compiler behind the scenes will convert your code into native application. Sounds great. This way you are not dealing with some HTML5 framework or a web solution but a real-world native application. Now all that you need to do is, stick with-in the boundaries of ES6 and React-native framework.

This framework has been tested and FB internally uses this framework to build some of their applications. Apart from FB, there are a lot of other enterprises that are using React-Native for day-to-day applications. Rest assured that you are not the first man to walk this terrain. If you have not tried it, I'd encourage you to read on and give it a shot.

In this section, I will walk you through some simple applications I built to help you see through the advantage of building React-Native application. Things like authentication, weather service, modal applications, better navigation etc are some. These are not typical applications that do the job of showing how to use some basic UI components, but I have weaved together components with application functionality that you can apply for your respective cases. Please stay tuned.....

Monday, October 10, 2016

rocky.js - Pebble Watchface in JavaScript

Create diagital watchface with rocky.js

Pebble is a familiar name in tech world. They were the one's who made the world turn on them when it comes to smart watches. When wearable technology was a dream, their design and approach made them great innovators. They followed it up with Pebble steel which did a wonderful business. Their OS agnostic approach has helped them gain love from both iOS & Android folks. Pebble has made a huge market for itself through its constant innovation and focus. With Pebble2, they have raised the bar a little more. I am not going to review about Pebble2 here. Our interest here is their new JS framework - rocky.js.

Pebble applications have been built with Pebble "C" and to some extent with Pebble JS. With Pebble 4 SDK, rocky.js will be one of the preferred way for pebble apps. rocky.js can be used to develop both watchface's as well as watch apps. Its support for canvas, makes it easy to render complex graphics fast too.

Although, I'd not rank rocky.js to be production ready yet, I'd also not shy away from saying that is is not far off from production grade either. Give it a month, by the time Pebble Time2 comes out to market, I'd say rocky.js may be the face of pebble application development.

What do I need to get started?
Head to developers.pebble.com, register your account and browse into cloudpebble.net, start cranking your code

Let's start by creating a new project, name it "HelloWorld"



You will be taken to cloud studio, from the left navigator, tap/select index.js



We will build our first simple display current time watch face, copy paste the following lines of code

var rocky = require('rocky');
var formatAMPM = function(date) {
  var hours = date.getHours();
  var minutes = date.getMinutes();
  var ampm = hours >= 12 ? 'pm' : 'am';
  hours = hours % 12;
  hours = hours ? hours : 12; // the hour '0' should be '12'
  minutes = minutes < 10 ? '0'+minutes : minutes;
  var strTime = hours + ':' + minutes + ' ' + ampm;
  return strTime;
}
var display_time = function(ctx) {
  // Determine the width and height of the display
  var w = ctx.canvas.unobstructedWidth;
  var h = ctx.canvas.unobstructedHeight;
  var d = new Date();
  // Set the text color
  ctx.fillStyle = 'white';
  // Center align the text
  ctx.textAlign = 'center';
  ctx.font = '30px bolder Bitham';
  // Display the time, in the middle of the screen
  ctx.fillText(formatAMPM(d), w/2, 50, w);
}
rocky.on('draw', function(event) {
  // Get the CanvasRenderingContext2D object
  var ctx = event.context;
  // Clear the screen
  ctx.clearRect(0, 0, ctx.canvas.clientWidth, ctx.canvas.clientHeight);

  display_time(ctx);

});
rocky.on('minutechange', function(event) {
  // Request the screen to be redrawn on next pass
  rocky.requestDraw();
});

Most of the the code is self-explanatory. We start by registering for event-notifications from rocky. One for 'minutechange' (you can try 'secondchange', 'hourchange', etc) and other for redraw. Every minute, code invokes redraw, where-in we display current time through a custom format function.

You are restricted on size and type of fonts, pretty much the same as in "C". However, you can have custom fonts for your applications.

You are all set. Tap on "run", wait and watch your code execute

Tuesday, October 4, 2016

Authentication in NodeJS

We all know and have done authentication for variety of applications - be it on web, mobile, windows or mac applications. The challenge with authentication lies on a couple of different fronts

  1. How easy it is for different applications to integrate and use the same authentication mechanisms
  2. How easy is it to use different strategies without breaking client applications


Its lot more easier said than done. In the past, client application will accept user names and passwords, encrypt credentials and send them over to a safe network and will wait for authentication status from server(s). This works great if we have a singular repository for authentication. Todays users have too many accounts to remember, one would think, its lot more easier to use any of the social network for authentication, while authorization can be managed internally. Such a solution will need more work from both client and server side on one dimension. But from the other dimension, it requires less work in terms for process. Client applications help user choose from one of many social engineering repositories, captures information and passes it to the server. While the server, does not digest this information, but rather, reaches out to the selected repository for information, gets back minimum profile information, along with a token identifier that can be used for back-forth communication. As long as all of the information from the server is available in request header, communication has no problems. If either TTL expires or the request header is manipulated, then authentication process is broken and the user is no longer identified as a authenticated user. He'll be re-directed to logon screen. Behind the scenes, developer needs to classify what constitutes secure paths and what are open for public, which is pretty much like the way he has to do for any regular secure application. No changes there. Enough talking. Lets get down to business.

How about creating a simple NodeJS application that will help you authenticate with different repositories like - Google+, Facebook, Twitter, LinkedIn etc? Sounds exciting. Here' how we can do it

Create a simple NodeJS application and see it work on the choice of your port. I prefer port 3000, you can choose any port of your choice. Once you have the intiial setup, head on to https://developers.facebook.com/, from there choose "My Apps". Tap on "Add a New App". You'll get a pop over, fill in the details, like display name, description, type of application etc. Now, in "Settings" section provide additional information like "App domain", which in our case will "localhost:3000" callback URL will be "http://localhost:3000/auth/facebook/callback". This is the URL that FB application will call us back on, after both successful or failed logon, with appropriate response. Note down App Id and secret key information from FB's site. Under Products section, you'll see "Facebook Login". Under "settings", make sure you set "http://localhost:3000/auth/facebook/callback" for "Valid OAuth redirect URIs".

Now, back in our node application, let's build strategies to handle this. For us to let application talk to FB, we need some more basic set up

Open terminal, navigate to your root directory of node application

npm init
npm install passport --save
npm install passport-facebook --save
npm install passport-github --save
npm install passport-linkedin-oauth2 --save
npm install passport-google-oauth --save
npm install body-parser --save

Each of these npm packages installed allow us to interface with respective authentication repositories. Now, back to FB's authentication. Import passport and passport-facebook packages into your application


var passport = require('passport');
var FacebookStrategy = require('passport-facebook').Strategy;

app.use(passport.initialize());
app.use(passport.session());

passport.use(new FacebookStrategy({
    clientID: AppConstants.FaceBook.appId,
    clientSecret: AppConstants.FaceBook.secretKey,
    callbackURL: BASE_URL + AppConstants.FaceBook.callbackURL
}, function (accessToken, refreshToken, profile, done) {
    process.nextTick(function () {
        done(null, profile);
    });
}));

We set the application use passport, passport session and FacebookStrategy as its middleware. Either replace  'AppConstants.FaceBook.appId' and 'AppConstants.FaceBook.secretKey' with the one you got from FB's site, or you can create a separate file with this information. Both of these are less secure, although, later one is slightly better. Personally, I'll store secret key and appID information in a remote location and fetch it when the application starts, or dump it in a secure remote DB, or even better store it as an environment variable. For this sample application, we are fine with any approach.

Now to handle callback from FB, here's what you amy want to do in your router configuration


// Facebook Router
router.get('/auth/facebook', passport.authenticate('facebook'));
router.get('/auth/facebook/callback', passport.authenticate('facebook', {
    successRedirect: '/success',
    failureRedirect: '/error'
}));

router.get('/success', function (req, res, next) {
    if(req.session != null) {
        console.log('Session information');
        console.dir(req.session);
    } else {
        console.log('SESSION is NULL');
    }

    res.redirect(302, 'home');
});
router.get('/error', function (req, res, next) {
    res.send("Error logging in.");
});
router.get('/', function (req, res, next) {
    res.sendfile('public/login.html');
});

And that's it. If your authentication is successful, you'll be re-directed to "home" page. You can follow this same procedure for all other authentication strategies like LinkedIn, Twitter, Google and Github. Working code for all of this is available in location

Sunday, June 12, 2016

Angular2 - Pipes

What are pipes? A pipeline is a sequence of processes chained together by their standard streams, so that the output of each process (stdout) feeds directly as input (stdin) to the next one. Straight from Wikipedia, yeahhhh.

Pipes in Angular are no different. There are a lot of things we can achive with it, but I'd advice you from going overboard. Always check to see if there is a better place/way to do this. If the transformation is one-time and is not complicated, fair enough, do it on the client side. The moment you see the same transformation done more than once, think about a custom pipe. Even with custom pipe you'd want to make sure it is simple. If it gets complicated, try to handle it on server side (in service). Keep client light & clean, make your code less buggy and light.

Angular2 allows for different types of pipes - Literal, Number, Currency, Date, Object and so much more. If the templated pipes are not enough, you can customize and create a pipe of your own. We will not delve into custom pipes in this BLOG. Let's save that for later

First, let's do a currency pipe
Add a new component - currency.component.ts & Pipes.service.ts

pipes.service.ts


import {Injectable} from "angular2/core";

@Injectable()
export class PipesService {
    getToDaysDate():Date {
        return new Date();
    }

    getApplicationVersion(): number {
        return 1.0;
    }

    getApplicationBuild(): number {
        return 12321;
    }

    getDollarValue(): number {
        return 15.41;
    }

    getEuroValue(): number {
        return 40.003;
    }

    getRandomData() {
        //TODO: Make this an array and return something randomly
        return "Some data";
    }
}

That's the service we will use for all components we will create from now on.

currency.component.ts

import {Component, OnInit} from 'angular2/core';
import {PipesService} from "./pipes.service";

@Component({
    selector: 'currency-comp',
    template: `
        <h5>Today's currency values</h5>
        <div class=".pipes">
            <ol>
                <li>{{dollarValue | currency:'USD':true}}</li>
                <li>{{euroValue | currency:'EUR':false:'1.4-4'}} </li>
            </ol>
        </div>
    `,
    providers:[PipesService],
})
export class CurrencyComponent implements OnInit {

    dollarValue: number;
    euroValue: number;
    
    constructor(private _pipesService: PipesService) {}

    ngOnInit():any {
        this.dollarValue = this._pipesService.getDollarValue();
        this.euroValue = this._pipesService.getEuroValue();
    }
}

As you see, cdollarValue is a number variable, we use currency pipeline to convert it to a currency field. Take a look at https://angular.io/docs/js/latest/api/common/CurrencyPipe-class.html to know more on parameters and other choices

Add a new component

date.component.ts

import {Component, OnInit} from 'angular2/core';
import {PipesService} from "./pipes.service";
import {MyVersionComponent} from "./version.component";

@Component({
    selector: 'myDate-comp',
    template: `
        <div class="pipes">
            <table width="100%">
                <tr>
                    <td><h2>{{today | date:'short'}}</h2></td>
                    <td align="right"><myVersion-comp align="right"></myVersion-comp></td>
                </tr>
            </table>
        </div>
    `,
    directives: [MyVersionComponent],
    providers: [PipesService],
})
export class MyDateComponent implements OnInit {
    constructor(private _pipesService:PipesService) {
    }

    today:Date = null;

    ngOnInit():any {
        this.today = this._pipesService.getToDaysDate();
    }

}

Here, we do something like what we did in currency component. Now you see the familiar pattern of how pipes work. To know more check https://angular.io/docs/js/latest/api/common/DatePipe-class.html

Most of the other pipes work very much the same way, except for one  AsyncPipe. It's different from other

randomAsync.component.ts



import {Component, OnInit} from 'angular2/core';

@Component({
    selector: 'async-comp',
    template: `
        <h5>Async - Random</h5>
        <div class=".pipes">
            {{randomData | async}}
        </div>
    `,
})
export class RandomAsyncComponent {

    randomData: string = new Promise((resolve, reject) => {
        setTimeout(() => resolve('Random Data!'), 2000);
    });
}

To understand AsyncPipe better, knock of " | async" out of code, see the behavior and put it back. You'll notice that this pipe will be one of the most used pipes of all of them.

Finally, if you are wondering, how I have my app component, here's how I have aggreagated the rest of them

app.component.ts

import {Component} from 'angular2/core';
import {MyDateComponent} from './date.component'
import {CurrencyComponent} from "./currency.component";
import {RandomAsyncComponent} from "./randomAsync.component";

@Component({
    selector: 'my-app',
    template: `
       <h1>Angular 2 - Sample Pipes</h1>
        <p>Welcome to the world of Angular2 Pipes</p>
        <myDate-comp></myDate-comp>
        <currency-comp></currency-comp>
        <async-comp></async-comp>   
    `,
    directives: [MyDateComponent, CurrencyComponent, RandomAsyncComponent],
})
export class AppComponent {

}

app.scss

body {
  padding: 32px;
  margin: 32px;
  font-family: "Roboto", Arial, sans-serif;
  font-size: 16px;
}

.pipes {
  margin: 32px 0;
  padding: 16px;
  background-color: #eee;
  border: 1px solid #ccc;
}

Angular2 - http GET/POST

What's the use of an application that does not talk with a remote datastore to persist or retreive information. This is one that I was looking forward to when I started Angular2. I believe it's the same with you. We are not going to make a deep dive, but rather touch enough piece to help you move along.  We will need a remote service that can persist contact information and give us back the contact list. For this exercise, I have created a sample NodeJS service that'll do the job - https://javascriptkrishnan.blogspot.com/2016/05/nodejs-mongodb-communication.html. Code is not pristine, but certainly get's us going. This NodeJS solution persists contact data passed to it in MongoDB and get's it back to us when requested. If you try this solution, please make sure you install and have accessible MongoDB. It's not just enough you have MongoDB, you need to fix it's access. Ensure right credentials are passed. How do you store user name and password for MongoDB in your Node JS solution. There are so many patterns. However, a simpler solution can be found here - https://javascriptkrishnan.blogspot.com/2016/06/application-initialization-dev-vs.html

Alrighty, what do we change in our code to be access this http service? Fairly simple. Remember we implemented mock services, it comes handy. All that we need to do is fix the services file to import http module and get data from remote location, instead of mock service. Here's the updated code. You may want to brush your knowledge on Promises

ContactsService.ts

/**
 * Created by krishnansriramrama on 5/28/16.
 */


import {Injectable} from "angular2/core";
import {Http, Headers} from "angular2/http";
import 'rxjs/Rx';
import {Contact} from "./Contact";

@Injectable()
export class ContactsService {
    ENPOINT_URL:string = "http://localhost:3000/contacts";

    constructor(private _http: Http){}

    getAllContacts() {
        return this._http.get(this.ENPOINT_URL).map(res => res.json());
    }

    saveContact(contact: Contact) {
        var contactBody: string = contact.toString();
        var header = new Headers();
        header.append('Content-Type', 'application/json');
        console.log("Saving contact: " + contactBody);
        return this._http.post(this.ENPOINT_URL, contactBody, {headers: header}).map(res => res.json());
    }
}

Saturday, June 11, 2016

Angular2 JS - Dependency Injection

So far we created components, added services. For us to understand few other tricks in dependency injection, though subtle, we may have to start from first. Let's create a new application from seed, and add couple of components. This exercise will also help you get you familiar with component creation process.

app.component.ts
/**
 * Created by krishnansriramrama on 6/1/16.
 */
import {Component} from 'angular2/core';
import {Component1Component} from "./component1.component";
import {Component2Component} from "./component2.component";

@Component({
    selector: 'my-app',
    template: `
        <div class="row">
            <div class="col-md-6">
                <my-component1></my-component1>
            </div>
            <div class="col-md-6">
                <my-component2></my-component2>
            </div>
        </div>
    `,
    directives: [Component1Component, Component2Component]
})
export class AppComponent {

}


Add 2 components, pretty simple one's. They add new items into array. Our exercise is to see if items we add in one component, reflects on the other. If we add services to component through "dataProviders", which I encourage you to try by yourself, you'll notice that items added in one component, does not show up in the other. If you wonder why? It's because, Angular2 creates 2 different instances of service object and shares it with components. That explains to why we data was not shared. What's the other approach you as. Keep following

component1.component.ts 

/**
 * Created by krishnansriramrama on 6/1/16.
 */
import {Component, ElementRef, OnInit} from 'angular2/core';
import {DataService} from "./data.service";

@Component({
    selector: 'my-component1',
    template: `
        <div class="panel panel-default">
            <div class="panel-heading"><h1>Component 1</h1></div>
            <div class="panel-body">
                <button (click)="onGetData()">Get random data</button>
                <p>Random data: {{data}}</p>
                <input type="text" #input>
                <button (click)="onAddItem(input.value)">Add</button>
            </div>
        </div>
    `,
})
export class Component1Component {
    data:string;

    constructor(private _dataService:DataService){}

    onGetData() {
        this.data = this._dataService.getRandomData();
    }
    
    onAddItem(data:string) {
        this._dataService.insertData(data);
    }
    
}

component2.component.ts 

/**
 * Created by krishnansriramrama on 6/1/16.
 */
import {Component} from 'angular2/core';
import {DataService} from "./data.service";

@Component({
    selector: 'my-component2',
    template: `
        <div class="panel panel-default">
            <div class="panel-heading"><h1>Component 1</h1></div>
            <div class="panel-body">
                <button (click)="onGetData()">Get random data</button>
                <p>Random data: {{data}}</p>
                <input type="text" #input>
                <button (click)="onAddItem(input.value)">Add</button>
            </div>
        </div>
    `,
})
export class Component2Component {
    data:string;

    constructor(private _dataService:DataService){}

    onGetData() {
        this.data = this._dataService.getRandomData();
    }

    onAddItem(data:string) {
        this._dataService.insertData(data);
    }
}

data.service.ts 


/**
 * Created by krishnansriramrama on 6/1/16.
 */
export class DataService {
    private _data = ['Milk', 'Brown Sugar', 'Bagel'];

    getRandomData() {
        return this._data[Math.floor(Math.random() * this._data.length)];
    }

    insertData(data: string) {
        this._data.push(data);
    }
}

For data service to be available to both components, we add it to boot.ts. Updated boot.ts looks like the following

boot.ts 
 
///
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from "./app.component";
import {DataService} from "./data.service";

bootstrap(AppComponent, [DataService]);

Run the app, you'll see data is shared amongst components. Hope that gives some context on dependency injection in Angular2 

Angular JS - Better form binding

We have "Add Contact" component working. But we are in search of a better way to do form bindings. The way we did in our previous exercise does work, but it is tough to keep up with a growing form. We want a better way and there is

new-contact.component.ts

/**
 * Created by krishnansriramrama on 5/28/16.
 */
import {Component, OnInit} from 'angular2/core';
import {ContactsService} from "./ContactsService";
import {Contact} from "./Contact";

@Component({
    selector: 'new-contact',
    template: `
<h2>Add a new contact</h2> <div> <form (submit)="saveContact()"> <div> <label>First Name</label> <input type="text" id="firstName" [(ngModel)]="formContact.firstName"> </div> <div> <label>Last Name</label> <input type="text" id="lastName" [(ngModel)]="formContact.lastName"> </div> <div> <label>EMail ID</label> <input type="text" id="emailId" [(ngModel)]="formContact.emailId"> </div> <div> <label>Phone Number</label> <input type="text" id="phoneNumber" [(ngModel)]="formContact.phoneNumber"> </div><br> <div id="formbox"> <button type="submit">Save contact</button> <button type="reset">Cancel</button> </div> </form> </div> `, styles:[ ` label { display: inline-block; width: 140px; text-align: right; margin: 10px; }​ input { margin-top: 5px; margin-bottom: 5px; display:inline-block; *display: inline; /* for IE7*/ zoom:1; /* for IE7*/ vertical-align:middle; margin-left:20px } #formbox { width:400px; margin:auto 0; text-align: center; } button { width: 125px; text-align: center; } ` ] }) export class NewContactComponent implements OnInit { formContact: Contact = new Contact(); postResponse = null; postError = null; constructor(private _contactsService:ContactsService) {} saveContact() { this._contactsService.saveContact(this.formContact).subscribe( response => this.postResponse = response, error => this.postError = error ); } checkAndPrintError() { console.log("POST complete"); if(this.postError != null) { console.log(this.postError); } else { console.dir(this.postResponse); } } }

What we have achieved here is pretty simple two-way binding. You may want to also read on observer pattern in Angular2.

Angular JS - Routes

Routes/Routers are the nervous system of an application. A well built routing system, will allow for right data to passed along, in the process keep the application clean. It's more often mess up in routes that adds to a lot of bad code. In the process, application development is strangled and brought to its knees. We are not going to look into best practices for routing, but a heads up on how to build routes in Angular 2. Later, we can build together another application that may possibly delve into more details.

Open up index.html, you should see <base href="/"> if you don't, please add it between <head> and <body> element. While you are on index.html, you'll notise boot.ts is one of the first few files loaded. Now open up boot.ts, inject ROUTE_PROVIDER

boot.ts 
///
import {bootstrap} from 'angular2/platform/browser';
import {AppComponent} from "./app.component";
import {ROUTER_PROVIDERS} from "angular2/router";

bootstrap(AppComponent, [ROUTER_PROVIDERS]);

Now that router provider is available, we will add choices for navigation in app.component. We don't have a lot to jump around. We will have 2 items, but whether we have 20 items here or just 2 items, the way things work will be the same

We will have 2 items to navigation between
1. List all contacts
2. Add a new contact

We already have a component to list all contacts. Let's create a new component to add a new component. Add a new file call it 'new-contact.component.ts'

new-contact.component.ts
/**
 * Created by krishnansriram on 5/13/16.
 */
import {Component} from 'angular2/core';

@Component({
    selector: 'new-contact',
    template: `
        <h3>Add a new contact</h3>
    `,

})
export class NewContactComponent {

}

Now that we have bare bone new component to add a new contact, we will quickly add a navigation bar to test. Open up app.component.ts, make the following change. Notice import statement and directives.

app.component.ts
import {Component} from 'angular2/core';
import {ContactListComponent} from "./Contacts/contact-list.component";
import {ROUTER_DIRECTIVES, RouteConfig} from "angular2/router";
import {NewContactComponent} from "./Contacts/new-contact.component";

@Component({
    selector: 'my-app',
    template: `
        <header>
            <nav>
                <a [routerLink]="['Contacts']">Contacts</a>
                 <a [routerLink]="['NewContact']">NewContact</a>
            </nav>
            
        </header>
        <div class="main">
            <router-outlet></router-outlet>
        </div>
    `,
    directives: [ContactListComponent, ROUTER_DIRECTIVES]
})
@RouteConfig([
    {path: '/contacts', name:'Contacts', component: ContactListComponent, useAsDefault:true},
    {path: '/newcontact', name:'NewContact', component: NewContactComponent}
])
export class AppComponent {

}

Go ahead run the code. You should now see things work. But the navigation item by itself doe not really look like a menu item. I don't want to spend all my time dressing it, but let's do some basic setup styling

open app.css and make the following change

app.css

body{padding:32px;margin:32px;font-family:Roboto,Arial,sans-serif;font-size:16px}

.main, header, nav {
    width: 75%;
    margin: 32px auto;
}

header nav a {
    color: #233dcb;
    text-decoration: none;
    font-weight:bold;
}

header nav a:hover,
header nav a:active {
    color: #41abf2;
}

Our next step is to create a useful and a working new contact component. First, let's add service to support for new contact component. Open up contact.service.ts and make the following changes

contact.service.ts
import {Injectable} from "angular2/core";
import {MOCK_CONTACTS} from "./mock-contact";
import {Contact} from "./contact";

@Injectable()
export class ContactService {
    getContacts() {
        console.log("getContacts - ContactsService");
        return Promise.resolve(MOCK_CONTACTS);
    }

    insertContact(contact: Contact) {
        Promise.resolve(MOCK_CONTACTS).then((contacts: [Contact]) => contacts.push(contact));
    }
}

with service available open up new-contact.component.ts, make the following changes

new-contact.component.ts
/**
 * Created by krishnansriram on 5/13/16.
 */
import {Component} from 'angular2/core';
import {ContactService} from "./contact.service";
import {Contact} from "./contact";
import {Router} from "angular2/router";

@Component({
    selector: 'new-contact',
    template: `
        <h3>Add a new contact</h3>
        <div>
            <div>
                <label for="first-name">First Name:</label>
                <input type="text" id="first-name" #firstName>
            </div>
            <div>
                <label for="last-name">Last Name:</label>
                <input type="text" id="last-name" #lastName>
            </div>
            <div>
                <label for="designation">Designation:</label>
                <input type="text" id="designation" #designation>
            </div>
            <div>
                <label for="phone">Phone:</label>
                <input type="text" id="phone" #phone>
            </div>
            <div>
                <label for="email">EMail:</label>
                <input type="text" id="email" #email>
            </div>
            <div>
                <button (click)="onAddContact(firstName.value, lastName.value, designation.value, phone.value,email.value)">Create contact</button>
            </div>
        </div>
    `,
providers:[ContactService], styles:[` label { display: inline-block; width: 140px; } input { display: list-item; width: 250px; } `] }) export class NewContactComponent { constructor(private _contactService:ContactService, private _router: Router) {} onAddContact(firstName, lastName, designation, phone, email) { let contact:Contact = {firstName: firstName, lastName: lastName, designation: designation, emailId: email, phoneNumber:phone}; this._contactService.insertContact(contact); console.log('Added new contact: ' + contact.firstName + ' ' + contact.lastName); this._router.navigate(['Contacts']); } }

Notice some changes we have in this component. First, "providers", inline-styling and then constructor!!!

The way we have used constructor, it tells the class, create a local instance variable _contactService and instantiate it with value from constructor. This is a short hand way in typsecript

Next up, Watch how each input element in template, has "#attribute" (#firstName, #lastName, etc). This ID, is what's used by button click event to gather contents from each input field. This is a complicated way to achieve our objective, leave alone scalability. If we add couple more fields, we have to add the same ID's and also add them as parameters to onAddContact method. In addition we may also like to do validation, better error reporting. We definitely need a better way to achieve all of this. As always, Angular2 comes to our rescue. But that's for later. Finally, notice router.navigate method. That's how we go back to list component, right after we add a contacts.

Angular JS - Styles

We have managed to create components, services, we also saw how injection pattern works. There is something we have ignored for a long time, have a better styled UI. After all good styles make for better looking views

There are 2 ways we can style our components
1. Through css file
2. Do it inline

Style with CSS file
Add a new file in src/css directory - contact-list.css, paste this code in

contact-list.css 

ul {
    list-style-type: circle;
    margin:16px 0;
    padding:0;
}

li {
    cursor: pointer;
    transition: padding 0.3s;
    margin: 0;
    display: inline;
    font-size:16px;
}

li:hover {
    padding-left: 8px;
    color:#233dcb;
    font-weight:bold;
    border-left: 3px solid #233dcb;
}

.clicked {
    color: #233dcb;
    font-weight:bold;
}

Open up Contact-list.component.ts, add a property to component "styleUrls" and reference contact-list.css file.

Code is not much different from what we had in the past, except for "styleUrls" addition

Contact-list.component.ts


/**
 * Created by krishnansriram on 5/13/16.
 */
import {Component, OnInit} from 'angular2/core';
import {ContactDetailsComponent} from "./contact-details.component";
import {ContactService} from "./contact.service";
import {Contact} from "./contact";

@Component({
    selector: 'contact-list',
    template: `
        <ul *ngFor="#contact of contacts">
            <li (click)="onSelect(contact)" [class.clicked] = "selectedContact === contact">
                {{contact.firstName}} {{contact.lastName}}
            </li>
        </ul>
        <contact-details [contact]="selectedContact"></contact-details>
    `,
    directives:[ContactDetailsComponent],
    providers: [ContactService],
    styleUrls:["./../src/css/contact-list.css"]
})
export class ContactListComponent implements OnInit{
    public contacts:Contact[];
    constructor(private _contactService:ContactService) {
        
    }
    public selectedContact = {};

    onSelect(contact) {
        console.log("Header tapped");
        this.selectedContact = contact;
    }
    
    getContacts() {
        console.log("Load contacts - Contacts-list component ");
        this._contactService.getContacts().then((contacts:Contact[]) => this.contacts = contacts);
    }
    
    ngOnInit(): any {
        console.log("OnInit method is invoked");
        this.getContacts();
    }
}

Style component - inline
Now how about having styles inline. Open contact-details.component, like the way we add styleUrls, we can add "styles" property. It takes an array and watch out for the quote used in the property. It's the same quote we used for defining template.
Sample code below

contact-list.component.ts
 
/** * Created by krishnansriram on 5/13/16. */ import {Component} from 'angular2/core'; @Component({ selector: 'contact-details', template: ` <div> <div> First Name: <input type="text" [(ngModel)]="contact.firstName" id="first-name"> </div> <div> Last Name: <input type="text" [(ngModel)]="contact.lastName" id="last-name"> </div> <div> Designation: <input type="text" [(ngModel)]="contact.designation" id="designation"> </div> <div> Phone Number: <input type="text" [(ngModel)]="contact.phoneNumber" id="phone"> </div> <div> EMail Id: <input type="text" [(ngModel)]="contact.emailId" id="email"> </div> </div> `, inputs:["contact"], styles:[` label { display: inline-block; width: 140px; } input { width: 250px; } `] }) export class ContactDetailsComponent { public contact = {}; }

Angular JS - Services

We built multiple components, let's focus a bit on services. All contacts data are inline. Not a great way for an application. What we will do is allow for service component to be added. For the moment we will have mock service. I promise we will integrate with a real-service in coming exercises, when we deal with HTTP samples.

We will also see how we can do “injection” pattern in this exercise

Lets start by creating a simple interface for our Contact object. In the past we had "Contact" as a class. Now we will make this an interface and have it as a contract between component and service.

Create a file contact.ts in "Contacts" directory

contact.ts

/**
 * Created by krishnansriram on 5/14/16.
 */
export interface Contact {
    firstName: string,
    lastName: string,
    designation: string,
    emailId: string,
    phoneNumber: string
}  

We don't have real services yet, lets start by creating a mock service for data
Create a file mock-contact.ts and add the following

mock-contact.ts

/**
 * Created by krishnansriram on 5/14/16.
 */
import {Contact} from "./contact";
export const MOCK_CONTACTS: Contact[]  = [
    {firstName:"Krishnan", lastName:"Sriram", designation:"Mobile Architect", phoneNumber:"508 330 2744", emailId:"krishnan.srm@gmail.com"},
    {firstName:"Rohit",lastName:"Sharma", designation:"Mobility Director", phoneNumber:"508 330 2745", emailId:"rohit.sharma@gmail.com"},
    {firstName:"Amit", lastName:"Khanna", designation:"Cloud Director", phoneNumber:"508 330 2746", emailId:"amit.khanna@gmail.com"},
    {firstName:"Bhagwan", lastName:"Kommadi", designation:"Enterprise Architect", phoneNumber:"508 330 2747", emailId:"bhagwank@gmail.com"}
];

Create a file contact.service.ts. This is the service file that will be referenced in our components for data. Notice we have imported mock data from mock-contacts temporarily

contact.service.ts


/**
 * Created by krishnansriram on 5/14/16.
 */
import {Injectable} from "angular2/core";
import {MOCK_CONTACTS} from "./mock-contact";

@Injectable()
export class ContactService {
    getContacts() {
        console.log("getContacts - ContactsService");
        return Promise.resolve(MOCK_CONTACTS);
    }
}

Our next step is to consume this service. The way we are going to do that is by adding contact-service as a "dataprovider". In addition we add a helper method in component to invoke getContacts. We will also see a new concept - "Life cycle in Angular JS". Take a moment to read through it.
We start by implementing "OnInit" interface. This means we need to override ngOnInit. Spare extra attention on the case for both method and interface we added. one small change, you may spend hours debugging. Trust me, I had to do that and would not want anyone to go through the same. For the service to be injected we need to add a constructor that takes "ContactService" as a parameter. Angular will take care of creating instance of this service object for our component at appropriate time. And that's it. Here you go with the code

contact-list.component.ts

/**
 * Created by krishnansriram on 5/13/16.
 */
import {Component, OnInit} from 'angular2/core';
import {ContactDetailsComponent} from "./contact-details.component";
import {ContactService} from "./contact.service";
import {Contact} from "./contact";

@Component({
    selector: 'contact-list',
    template: `
        <ul *ngFor="#contact of contacts">
            <li (click)="onSelect(contact)" [class.clicked] = "selectedContact === contact">
                {{contact.firstName}} {{contact.lastName}}
            </li>
        </ul>
        <contact-details [contact]="selectedContact"></contact-details>
    `,
    directives:[ContactDetailsComponent],
    providers: [ContactService],
})
export class ContactListComponent implements OnInit{
    public contacts:Contact[];
    constructor(private _contactService:ContactService) {
        
    }
    public selectedContact = {};

    onSelect(contact) {
        console.log("Header tapped");
        this.selectedContact = contact;
    }
    
    getContacts() {
        console.log("Load contacts - Contacts-list component ");
        this._contactService.getContacts().then((contacts:Contact[]) => this.contacts = contacts);
    }
    
    ngOnInit(): any {
        console.log("OnInit method is invoked");
        this.getContacts();
    }
}

Angular 2 - contact to contacts list

It's great that we now can display contact information. But we seldom deal with single contact in real life. What we want to in here is to have a list of contacts. When the the user taps on a particular contact, we display more details in our case that is phone number & email Id. We could do all of that in app.component.ts. But that will not just bloat this file, but will also parse our capabilities to re-use. We don't want that do we?. It is better for us to break this into app.component to multiple components and have app.component as an aggregator. With multiple components, code gets better and we promote re-usability, with that comes communication issues. That's what we will learn in coming exercises

In the “Dev” directory, I created a new directory “Contacts” and added 2 files for our 2 new components
1. contact-list.component.ts
2. contact-details.component.ts

ContactList component, will list from array of contacts. Tap on any contact, ContactDetails component will show details. Like I said earlier, the most interesting part of this exercise is not just splitting one component into multiple components, it allows us to explore ways for components to communicate with each other. For the moment this communication is one way, in course of time, we will see how 2 way communication happens.

Take a look at "directives". It plays an important role in component development. Look at directives like #includes or imports. When JS parser hits on "<contact-details>", it immediately looks for directive information, in the process, it's definition. Also note, every directive component should also have its corresponding import statement too 

contact-list.component.ts
 
/**
 * Created by krishnansriram on 5/13/16.
 */
import {Component} from 'angular2/core';
import {ContactDetailsComponent} from "./contact-details.component";

@Component({
    selector: 'contact-list',
    template: `
        <ul *ngFor="#contact of contacts">
            <li (click)="onSelect(contact)">{{contact.firstName}} {{contact.lastName}}</li>
        </ul>
        <contact-details [contact]="selectedContact"></contact-details>
    `,
    directives:[ContactDetailsComponent]
})
export class ContactListComponent {
    contacts = [
        new Contact("Krishnan", "Sriram", "Mobile Architect", "508 330 2744", "krishnan.srm@gmail.com"),
        new Contact("Rohit", "Sharma", "Mobility Director", "508 330 2745", "rohit.sharma@gmail.com"),
        new Contact("Amit", "Khanna", "Cloud Director", "508 330 2746", "amit.khanna@gmail.com"),
        new Contact("Bhagwan", "Kommadi", "Enterprise Architect", "508 330 2747", "bhagwank@gmail.com")
    ];
    public selectedContact = {};

    onSelect(contact) {
        console.log("Header tapped");
        this.selectedContact = contact;
    }
}

class Contact {
    firstName: string;
    lastName: string;
    designation: string;
    phoneNumber: string;
    emailId: string;

    constructor(fname, lname, dsgn, phone, email) {
        this.firstName = fname;
        this.lastName = lname;
        this.designation = dsgn;
        this.phoneNumber = phone;
        this.emailId = email;
    }
}

contact-details.component.ts

/**
 * Created by krishnansriram on 5/13/16.
 */
import {Component} from 'angular2/core';

@Component({
    selector: 'contact-details',
    template: `
       <div>
            Designation: {{contact.designation}}<br>
            Phone Number: {{contact.phoneNumber}}<br>
            EMail Id: {{contact.emailId}}
        </div>
    `,
    inputs:["contact"]
})
export class ContactDetailsComponent {
    public contact = {};
}

app.component.ts 

import {Component} from 'angular2/core';
import {ContactListComponent} from "./Contacts/contact-list.component";

@Component({
    selector: 'my-app',
    template: `
        <h3>Contacts</h3>
        <contact-list></contact-list>  
    `,
    directives: [ContactListComponent]
})
export class AppComponent {
    
}

Now look at how beautiful our AppComponent is. CLEAN.

By now you know how to run your changes. Run the code and have fun building more components

Angular2 - Associate simple events on component

Let's continue from our previous exercise to associate some events. Here's what we want to do. Display Contact information but hide Phone number and email. When the user taps on First name or last name, we display them. You click on it again, we hide phone number and email. This will introduce how events within the components can be wired. It's easy small exercise. Remember - one step at a time

app.component.ts

import {Component} from 'angular2/core';

@Component({
    selector: 'my-app',
    template: `
        <div (click)="onSelect()"><b>{{contact.firstName}} {{contact.lastName}}</b></div>
        {{contact.designation}}<br />
        <input type="text" [(ngModel)]="contact.designation" />
        <ul *ngIf="showDetails == true">
            <li>Phone Number: {{contact.phoneNumber}}</li>
            <li>EMail Id: {{contact.emailId}}</li>
        </ul>
    `,
})
export class AppComponent {
    contact = new Contact("Krishnan", "Sriram", "Mobile Architect", "508 330 2744", "krishnan.srm@gmail.com");
    showDetails: Boolean = false;

    onSelect() {
        console.log("Header tapped");
        this.showDetails = !this.showDetails;
    }
}

class Contact {
    firstName: string;
    lastName: string;
    designation: string;
    phoneNumber: string;
    emailId: string;

    constructor(fname, lname, dsgn, phone, email) {
        this.firstName = fname;
        this.lastName = lname;
        this.designation = dsgn;
        this.phoneNumber = phone;
        this.emailId = email;
    }
}

We introduced quite a bit of changes from previous exercise. First, we changed the template. Modified top-most div tag to accept "select" event. Notice change in syntax. Later for "ul" element, we do a if on a class property to decide if we should show or hide more contact information. Also notice onSelect method. Pretty straight forward. that's it for now. Go ahead and try different events and have fun

My Angular2 Hello World

Any project we do it is very important for us to establish right design patterns. In JS world one of the most used and appreciated pattern is "Module pattern". It is also important that we don't re-invent wheel. There are plenty of seed applications for Angular2 for us to start with. I have tried a few and found below 2 to be the nice. In the sense they are not overtly intrusive to our ways of work. Off the 2, first one is more basic and better suited for our application. Later one is more useful for production grade applications. I'll have a separate post for that in coming days. Please take sometime to go over github links. There's not much as setup for both, except for download and init, followed by start. Since we seed this from github, you may need to understand what other components have been added namely - yomen, gulp, jasmine etc. If you are not interested in these frameworks, knock them off and continue.

I have tried a couple of seeds
1. https://github.com/mgechev/angular2-seed
2. https://github.com/mschwarzmueller/angular-2-beta-boilerplate

Here are your next steps
1. Download angular-2-beta-boilerplate-master.zip file from Github
2. Move zip file to a location of your choice
3. Unzip angular-2-beta-boilerplate-master.zip,
4. Open terminal, browse into root directory of unzipped file (which I persume would be angular-2-beta-boilerplate-master)
5. Do "npm install".
6. When all done and complete, execute "npm start"

This will open your browser and show HelloWorld Angular2 application.

If you see that, congratulations!!!. Welcome to the beautiful world of Angular2

What we embark on in this BLOG is incrementally build on a contacts application, in the process touch upon all new concepts in Angular2. I have gone very light and picked up "Contacts" project for a couple of reasons. There are so many "To Do" application that I had a brain dump on "To Do". And of course, I did not want much focus to go into domain. We want to touch upon as many Angular2 concepts. We'll make exceptions to "Contacts" application sample for few Angular2 blogs, but that will be way later

As mentioned in my earlier article, please take some time to go over Typescript before you join me in Angular2 journey.....choo, choooo and the train has hooted to signal that, it's leaving the station

Before we get started, please keep the zip file for bootstrap safely. We may need it a number of times. Each time you expand on the zip file, its a good practice to rename root directory to something that's more meaningful for your project.

Unzip angular-2-beta-boilerplate-master.zip and rename root directory to say "MyFirstApp" or anything of your choice. Let's bring up our first contacts page/component.

Open up app.component.ts and make the following changes. We change hello world template to display contact information.

app.component.ts

import {Component} from 'angular2/core';
@Component({
    selector: 'my-app',
    template: `
        <div><b>{{contact.firstName}} {{contact.lastName}}</b></div>
        {{contact.designation}}<br />
        <input type="text" [(ngModel)]="contact.designation" />
        <ul>
            <li>Phone Number: {{contact.phoneNumber}}</li>
            <li>EMail Id: {{contact.emailId}}</li>
        </ul>
    `,
})
export class AppComponent {
    contact = new Contact("Roger", "Fedrer", "Ace tennis star", "508 002 1324", "fed.express@outlook.com");
}

class Contact {
    firstName: string;
    lastName: string;
    designation: string;
    phoneNumber: string;
    emailId: string;

    constructor(fname, lname, dsgn, phone, email) {
        this.firstName = fname;
        this.lastName = lname;
        this.designation = dsgn;
        this.phoneNumber = phone;
        this.emailId = email;
    }
}

What we have done above with the selector is, display first name and last name in bold. Followed by designation. Load the same designation in a text field to show two-way binding is still an integral part of Angular. We loved it in Angular1. Our affair can continue in Angular2 too. Type in a different designation and see it show up in the display above. We follow that information with Phone number and email ID. There is a reason we have email and phone number in a separate DIV. You'll see that in a little bit.

Then comes our class "AppComponent", we create a new instance of contact. This instance is what is used in template. This is not an elegant way to either create a component or feed values into it. Definition of Contact class is right below, defined in Typescript

Now that's it. If you were using npm start, then the changes would already show up in the browser. If you had stopped it, you may have to re-run it. That's it for this BLOG. Will see you seeon with some events in the next one

Angular2 - A quick start

Preface

In today's world of modern technology, mobile solutions has taken off in the speed of photons. Everyone talks about building a web application wether they have a need for it or not. Studies have indicated that more than 40% of the businesses have seen no improvement by going mobile. They were doing as much business before they invested into mobile. Now does that mean we should not build mobile applications?. Nope. It only indicates to us that mobile technologies are not a viable alternative for web as yet. Further, it suggests, that mobile is a great supplement for web. From a developers perspective it conveys a lot more. Things that they have taken for granted in the past on UI will no longer escape eyes of end-users Like choice on controls, fonts, formats, page layouts, navigation, etc. Proliferation of mobile technology and mobile solutions has made life easy for users, they expect same sort of easy and convenient experience on web too.

UI is not the only change. In the past, when we start developing web applications, rarely did people think about 3-tier architecture. Except for enterprise solutions, most of the solutions were tightly coupled, wether for a reason or by mistake, is subjective.

We are left with 2 things from the past that we want to fix right away when we start building our application. Guess what, Angular2 helps you in both from the word go.

First on UI, Angular2 takes a deviation from the past. Rather than building a view, or a page, it now allows to think & build components that are reusable, either with-in the application or anywhere outside the scope of application. If the input and output directives are well defined, you have a seasoned machine that can run for ever (or at least till Angular3 comes along with bigger magic).

What about Angular1 & how does Angular2 fair compared to Angular1?

There are a lot of things that are different in Angular2, but that does not mean you are alienated. Angular2 is something that's inline with needs of todays requirements. How do I say? Look around all the latest UI frameworks from React to Sencha, all of them have changed development paradigm of yester-years. Building monolithic large applications into something that's smaller, faster, scalable, configurable solution. Angular2 will not be left behind in this approach. Angular1 had a lot of great features. Acceptability from developer community is a testimonial of how good it was. Angular2 takes it to another level - build components. Unless we build components, think of application as a conglomeration of components, we are seldom going to change the way they we write application.

How do we go from Angular1 to Angular2?

This post is more about Angular2. Towards the end of this, I'll try to put together things that we need to take care of for migration. Angular team has been talking about or they already have a migration tool that helps you in the conversion process. In addition, both Angular 1 and Angular2 can co-exist. This is good news to all Angular1 folks. It means you don't need to sweat it out over-night to convert all your Angular1 code to 2.X. Gives you time think through, get used to the newer ways of development, build bridges, get the infrastructure ready and change one page/view/component at a time and then have the entire app running on Angular2. Although I may not give you a very objective answer, I hope this at least allows time for a deep breath and tells you that all is not over.

What are we going to do here?

This is more a hands on exercise for Angular2. We'll build end-to-end solution on Angular2, in the process, touch on a variety of areas that will make it very easy for you to see how Angular2 fairs against some of the other web technologies and in the process gets you acquainted to new ways to handle things.

To start with I would say this will be a 15 - 18 part blog. In each step we will build on the solution one step further to understand Angular2 more. I may also want to caution you that we will not be able to cover Angular2 exhaustively. This is more of an attempt to introduce Angular2 concepts the way I learnt it from a lot of resources out there. With that introduction lets talk about what we are going to build. We build a SPA for contacts. It will have both form and list to allow for experience in both the world.

Kickstart

To start on application development we need a bootstrap to take care of several things folder structure to say the least, IDE, choice on languages etc

  • Download boilerplate code from here https://github.com/mschwarzmueller/angular-2-beta-boilerplate
  • I prefer using Webstorm. It does a lot of intellisence and imports great, but you can use what ever you are comfortable with
  • Typescript is what we will use in this case. You can learn a lot more from here https://www.typescriptlang.org/docs/tutorial.html

Application initialization - Dev vs production

Quite recently I was talking about NodeJS and the way it works to a bunch of developers. I was not impressed by the way they were handling application initialization states. Especially how they treated their production vs development environments and username and password. This is not the first case I have seen people spray their user names across application. I explained to them the need for keeping it clean. As much as I told them that, thought a short post will help everybody.

I prefer to use singleton for this case. These seldom change during development. With that said, I'd like to keep it very short. We have a simple app.js, that prints hello world. It will need to know if the application is running in DEV or PRODUCTION mode.

Here's the structure, I chose to go with



app.js


var environment = require('./environment')
console.log('Hello World!!!');
console.log(environment.environmentJSON());

env.json


{
 "development": {
  "aws_user_id": "facebook_dummy_dev_app_id",
  "aws_user_passwd": "facebook_dummy_dev_app_secret"
 },
 "production": {
  "aws_user_id": "facebook_dummy_prod_app_id",
  "aws_user_passwd": "facebook_dummy_prod_app_secret"
 }
}


environment/index.js


module.exports = require('./locateEnvFile');

environment/locateEnv.js


var env = require('./../env');
module.exports.environmentJSON = function locateEnvironmentJSONFile() {
    var node_env = process.env.NODE_ENV || 'development';
    return env[node_env];
};

Run app.js through node or nodemon. env information is available. No matter how many JS files you create in the application, you can now import/require environment in them and get information in a nicer way.

Saturday, May 28, 2016

Node JS streams

Streams in NodeJS

Streams in NodeJS are not as complicated as people perceive. Although it can easily go from mere to composite in a blink of an eye.

Streams help you to picture complicated business into its simplified version with a couple of lines of code. With all complications abstracted in a module so to say. This promotes code simplicity, re-usability and in the process more value for code. If you are willing to introspect code with and without streams you'll certainly observe 2 or 3 lines of code would have saved some 30 - 40 lines of code, especially for people who build APIs and SDKs

Lets start small and a meager activity. Copy a file from one location/directory to another. You'd ask why such a mundane activity.

fs.createReadStream(sourceFile).pipe(fs.createWriteStream(targetFile));

Where is the validation of source file and destination path etc. One step at a time. This is a simple file copy operation. If you capsule this line within a try-catch block, a lot of the issues that you are thinking about are handle inherently without any effort. Now, you can let your imagination go wild and build on this solution to copy directories, drives or more. Our next step is something that will be more useful from a day to day perspective

More than copying a file

Downloading file from a remote location. Something like say you want to download a s/w from a remote location over ftp/http/https etc. Automating such pieces would make it easier for us. Say for e.g You need to download a huge file from a remote location.

var request = require('request');
var path = require('path');
var REMOTE_LINK = "https://download.sublimetext.com/sublime_text_3_build_3103_x64.tar.bz2"
var LOCAL_DOWNLOAD_PATH = path.join(process.env.HOME, "Downloads");
var downloadFile = path.join(LOCAL_DOWNLOAD_PATH, path.basename(REMOTE_LINK));

request(REMOTE_LINK).pipe(fs.createWriteStream(downloadFile));

We can do some variations on this. You can associate events to let you know when streaming is done like the following and more.

request
 .get(REMOTE_LINK)
 .on('response', function(response) {
  console.log(response.length);
 })
 .on('error', function(err) {
  console.log('ERROR: Failed to download file: ' + err);
 })
 .on('end', function() {
  console.log('Completed file download successfully');
 })
 .pipe(fs.createWriteStream(downloadFile));

Above code is not only methodical, but serves as a documentation, with clear logs on each step. Even a novice developer will be able to follow with ease.

What we downloaded was a bz2 file, what if we need to download and unzip too in one short?
That will be an exercise for you. What I can share though is check on npm pack utilities for 'untar', 'gunzip' etc

Let's look into a related example. How to unzip a .tar.gz2 file, get .tar. Here we go

fs.createReadStream(sourceFile)
 .pipe(zlib.createGunzip())
 .pipe(fs.createWriteStream(unzippedFile));

Alright, we unzipped a file, but we still just have a .tar file. How about extracting a tar after we unzip it

var tar = require('tar-fs');
var fs = require('fs');

if(process.argv.length < 4) {
    console.log('ERROR: Please pass on TAR file name followed by location to extract the file, to continue');
    process.exit();
}

const SOURCE_FILE = process.argv[2];
var DEST_PATH = process.argv[3];

var untarFile = function(sourceFile, targetPath) {
    try {
        fs.createReadStream(sourceFile).pipe(tar.extract(targetPath));
    } catch(e) {
        console.log(e);
        process.exit();
    }
}

untarFile(SOURCE_FILE, DEST_PATH);

Transformation solutions

So far we saw how to write NodeJS-stream code and download, unzip or tar file. How about little more serious activity relevance to translation/transformation of data. Say, we get stream of data and we wish to convert it to upper case, pass it along for further processing . Although this does not look like a day-to-day business problem, it helps to show case the potential of NodeJS streams. I'd consider this to be a seed solution for your business problems.

CapitalizingStream.js

var inherits = require('util').inherits;
var Transform = require('stream').Transform;

module.exports = CapitalizingTransformStream;

function CapitalizingTransformStream(options) {
    Transform.call(this, options);
}

inherits(CapitalizingTransformStream, Transform);

function _transform(chunk, encoding, callback) {
    if(encoding == 'buffer') {
        chunk = chunk.toString();
    }
    callback(null, chunk.toUpperCase());
}

CapitalizingTransformStream.prototype._transform = _transform;

ConvertCase.js

var net = require('net');
var CapitalizingStream = require('./CapitalizingStream');

function handleConnection(conn) {
    var remoteAddress = conn.remoteAddress + ':' + conn.remotePort;
    console.log('New client connection from %s', remoteAddress);
   
    // handle connection to service
    var service = new CapitalizingStream();
    service.once('error', onServiceError);

    conn.once('close', onConnectionClose);
    conn.on('error', onConnectionError);

    conn.pipe(service).pipe(conn);

    function onServiceError(err) {
        console.log('ERROR: %s', err.message);
    }

    function onConnectionClose() {
        console.log('Connection closed on :%s', remoteAddress);
    }

    function onConnectionError(err) {
        console.log('Connection %s error %s', remoteAddress, err.message);
    }
}

var server = net.createServer();
server.on('connection', handleConnection);
server.listen(9000, function() {
    console.log('Server listening to %j', server.address());
});

Though above solution may not have have much of industrial value, here's is something you can try on as an exercise and check your stream skills
  • Convert CSV to HTML. Pass this CSV contents from a remote location
  • Accept content, convert to HTML
  • Send it back

More automation with NodeJS

  • Downloading files in clusters for setup - sort of containers for download. Such solution helps people do setups for OS, their dev environment etc. Something like dockers, in a much much smaller scale
  • Download your favorite/bookmarks from youtube. Persist links in a store, periodically download it and convert mp3 to say mp4 or other formats
  • Reverse Proxy - Make application performance better through reverse proxy. Build gateway engines.
  • Build easy cache - Addition to above approach. 

NodeJS-Mongodb Persistent store

Multi-Tier applications

When we build web applications one of the most essential piece is services. Gone are the days we used to build single tier applications. We now have at a minimum 3-tier's to build on applications.

  • Tier-1 is UI
  • Tier-2 is services
  • Tier-3 is DB

What we will do in coming days

Real-time applications have a lot more. There will be at least 6-tiers which includes security, availability and performance tiers. For our case, we don't need that. But later we will see 



  • How to improve speed with NGINX on NodeJS solutions (performance) 
  • How to implement caching solutions with Reddis (Performance) 
  • How to use RabbitMQ with NodeJS (security & scalability) 
  • How to do authentication with NodeJS (security) 


3-Tier(s) are not perceptible logical layers, but in most occasions physical too. Running in different physical locations, systems, servers makes the application more manageable & testable.

So far in NodeJS samples we built, none of them help us persist data permanently. Our objective now is to connect NodeJS with MongoDB in the process persist data.

Install MongoDB

If you have not installed MongoDB, here's how you can do it
http://techkrishnan.blogspot.com/2016/05/installing-mongodb-osx.html

Install needed packages

We start in a less modular fashion to be conspicuous. As we expand we will have introduce other design patterns.

In addition to installing 'mongodb', I also installed the following 'querystring' and 'mongodb' client from npm

npm init
npm install querystring --save
npm install mongodb --save

Let's get started

Code to connect to MongoDB is below. Lets take a moment to dissect & understand what we got.

We connect to MongoDB using 'mongodb' package. It is through this client utility we connect to data store. We then define URI to connect to datastore. Connect method takes URI and callback as parameters. Always check for 'error' in callback, if error is NULL we return, else we proceed with the returned object - DB handle.

DB handle gives us baton to query for collection "contacts". MongoDB is a document DB, we do not have schema defined on it. Simple JSON object defined can be added into collection. Every documents in collection can be completely different. It is important on each step we check to see if we have right handle or received error. If it is an error, we return.

We have got code for OPTIONS method, we will talk about it in coming sessions

With the collection handle, next step is to check for GET and request path. If the path is what we are looking for we list the contents. MongoDB as asserted earlier is a document DB, which stores JSON collections. For us to interact over web, we need to convert this JSON objects into text (we could alternatively have 'content-type' set to 'application/javascript') for the sake of simplicity. Invoke find method on collection. If we receive error, we stop, else we return list of objects.

We move towards our next objective to insert data. We check to see if request method is POST and url is for 'contacts'. POST method passes data in BODY. We need to tune into HTTP events to access data. Once we have data, we convert it to 'utf-8' type string for processing, remmeber we sent data in RAW format from POSTMAN. Convert the string data received into JSON. If there are issues in conversion process, application may crash. To avoid such fallibilities we encompass conversion in try-catch block. We now have data that can be inserted into collection. This is done by invoking insert method. Again check with callback method for errors, if not, return the object which conveys how many objects were inserted.

How do we test this?

I suggest you install 'PostMan REST client' from Chrome/Firefox/Safari extension.

List contents


  • Open POSTMAN, 
  • choose GET method and set URL to be 'http://localhost:3000/contacts'. 
  • Tap on "SEND" method. 
  • If 'contacts' collection has data, we will see all of them . If there is no data, nothing comes back. 

Add/Insert content


  • We test POST method. Set method to 'POST', URL to be 'http://localhost:3000/contacts'
  • To pass data, select 'BODY' and ensure 'raw' option is selected with JSON (application/json) format. Add following data 
  • {"firstName":"someName1","lastName":"someName2","emailId":"someName@outlook.com","phoneNo":"XXX-XXX-3244"}
  • Tap on send. 


Now go back to GET, you should see inserted document(s).

/**
 * Created by krishnansriramrama on 5/27/16.
 */
var http = require('http');
var util = require('util');
var querystring = require('querystring');
var client = require('mongodb').MongoClient;

var uri = process.env.MONGOLAB_URI || 'mongodb://@127.0.0.1:27017/krishnan';

client.connect(uri, function(error, db) {
    if(error) {
        return console.error(error);
    }

    var collection = db.collection('contacts');
    var app = http.createServer(function(request, response) {
        var origin = (request.headers.origin || '*');
        if(request.method === 'OPTIONS') {
            response.writeHead('204', 'No Content', {
                'Access-Control-Allow-Origin': origin,
                'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, OPTIONS',
                'Access-Control-Allow-Headers': 'content-type, accept',
                'Access-Control-Max-Age': 10,
                'Content-Length': 0
            });
            response.end();
        } else if(request.method === 'GET' && (request.url === '/contacts' || request.url === '/contacts/')) {
            collection.find().toArray(function(error, results) {
                if(error) {
                    return console.error(error);
                }
                var body = JSON.stringify(results);
                response.writeHead('200', {
                    'Access-Control-Allow-Origin': origin,
                    'Content-Type': 'text/plain',
                    'Content-Length': body.length
                });
                console.log('List of objects returned from DB');
                console.dir(results);
                response.end(body);
            });
        } else if(request.method === 'POST' && (request.url === '/contacts' || request.url === '/contacts/')) {
            request.on('data', function(data) {
               console.log('Received Data');
                data = data.toString('utf-8');
                console.log(data);
                try {
                    data = JSON.parse(data);
                } catch(error) {
                    if(error) {
                        return console.error(error);
                    }
                }
                collection.insert(data, {safe:true}, function(error, obj) {
                   if(error) {
                       return console.error(error);
                   }
                    console.log('Object is saved');
                    console.log(JSON.stringify(obj));
                    var body = JSON.stringify(obj);
                    response.writeHead(200, {
                        'Access-Control-Allow-Origin': origin,
                        'Content-Type': 'text/plain',
                        'Content-Length': body.length
                    });
                    response.end(body);
                });
            });
        } else {
            response.end('Supported endpoints: GET /contacts, POST /contacts');
        }
    });
    var port = process.env.PORT || 3000;
    app.listen(port, function() {
        console.log('Server running in port - ' + port);
    });
});