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.