Friday, December 30, 2016

JavaScript Evolution ESMAScript 6 - Promises

Typically, to avoid blocking the main thread of execution, we write non-blocking code using asynchronous style function pass callback like this:
getResult("Saas", function(result) {
  ui.renderSidebar(results);
}
When nested callbacks start to grow, our code becomes harder to read. We have to check for error on every callback.
getResultFromServer("Saas", function(error, results) {
  if (error) { // handle error };
  ui.renderSideBar(results, function(error, results) {
    if (error) { //handle error };
    sendNotificationToServer(results, function(error, response) {
      if (error) { // handle error };
      doSomethingElse (response, function(error)) {
        if (error) { //handle error };
        //...
      };
    };
  };
});
Promises brought to JavasScript trying to offer a solution to this issue by bringing new abstraction that allows us to write asynchronous code in an easier way.
getResultFromServer("Saas")
  .then(ui.renderSidebar)
  .then(sendNotificationToServer)
  .then(doSomethingElse)
  .catch(function(error) {
    console.log("Error :" + error);
  }
The Promise constructor function takes an anonymous function with 2 callback argument known as handles. Handles are responsible for resolving or rejecting the Promise.

Create a new Promise automatically set it to the pending state. Then, it can become fulfilled(resolve) or rejected(reject).

One thing to remember is that Promise not return a result, its return a future value, such as the eventual result if asynchronous operation.

Let's wrap the XMLHttpRequest object API within a Promise. Calling the resolve() handler moves the Promise to a fulfilled state. We'll call the reject() handler for unsuccessful status codes and also when the error event is triggered on our request object. Both move the Promise to a rejected state.
function getResultFromServer(pollName){
  return new Promise(function(resolve, reject) {
    request.onload = function() {
      if (request.status >= 200 && request.status < 400) {
        resolve(request.response);
      } else {
        reject(new Error(request,status));
      };
    };
    request.oneerror = function() {
      reject(new Error ("Error Fetching Results"));
    };
  };
};
We can use then() method to read results from the Promise once resolved. We can chain multiple calls to then(). The return value from 1 call is passed as an argument to the next.

Once an error occurs, execution moves immediately to the catch() function. None of the remaining then() function are invoked.
getResultFromServer("Saas")
  .then(function(result){
    // Return value to next then().
    return result.filter((result) => result.city === "Orlado");
  })
  .then(function(resultFromOrlando){
    ui.renderSideBar(resultsFromOrlando);
  })
  .catch(function(error) {
    console.log("Error : " + error);
  })

Friday, December 23, 2016

JavaScript Evolution ESMAScript 6 - Module

In this section, we learn about using Module to encapsulate classes.

To export classes, use the export syntax with the class name inside curly braces.

flash-message.js
class FlashMessage {

  constructor(message) {
    this.message = message;
  }

  renderAlert() {
    alert(`${this.message} from alert`);
  }

  renderConsole() {
    console.log(`${this.message} from log`);
  }

}

export {FlashMessage} // Export class to outside world.
To import the class, we must use the same export name.

app.js
import {FlashMessage} from './flash-message';

let flash = new FlashMessage('Hello');
flash.renderAlert(); // Alert -> Hello from alert
flash.renderConsole(); // Console -> Hello from log

JavaScript Evolution ESMAScript 6 - Classes

A common encapsulation approach in JavaScript is using construction function. Adding the prototype required a bit of coding and some repetition. We can do better using new Class syntax to write the object-oriented language.

To define a class, we use class syntax followed by the name of the class. The body of a class is the part between curly braces.

Currently, there is no access modifier in JavaScript, like private and protected in another language. Prefixing a method with an underscore is a convention for indicating that it shouldn't be invoked from public API.
class SponsorWidget {
  // Constructor method is a special method for creating and initializing an object.
  // Its run every time a new instance is created with the new operator.
  constructor(name, description, url) {
    this.name = name;
    this.description = description;
    this.url = url;
  }

  // Private method
  _buildURL(url) {
    console.log(url);
  }

  // Instance method definition in classes look just like the method initializer shorthand in object.
  render() {
    // Variable set in constructor can be accessed from all other instance method using this. syntax.
    let link = this._buildURL(this.url);
  }
}

// Here is how we involve the class
let sponsorWidget = new SponsorWidget(
  "Google",
  "Search",
  "https://www.google.com"
);

sponsorWidget.render();

One benefit of class syntax is that we can use class inheritance. The extends syntax is used to create a class that inherit methods and properties from another class. The super method runs the constructor function from the parent class.
// Parent Class
class Widget {
  constructor() {
    this.baseCSS = "site-widget";
  }

  parse(value) {
    console.log(this.baseCSS);
  }
}

// Child Class
class SponsorWidget extends Widget {
  constructor(name, description, url) {
    super(); // Run parent constructor.
    this.name = name;
    this.description = description;
    this.url = url;
  }

  _buildURL(url) {
    console.log(url);
  }

  render() {
    let link = this._buildURL(this.url);

    // Calling inherit property and method
    this.parse(this.baseCSS);
  }
}
You can override the inherited method by naming the same method name in child class.
// Parent Class
class Widget {
  constructor() {
    this.baseCSS = "site-widget";
  }

  parse(value) {
    return this.baseCSS;
  }
}

// Child Class
class SponsorWidget extends Widget {
  constructor(name, description, url) {
    super(); // Run parent constructor.
    this.name = name;
    this.description = description;
    this.url = url;
  }

  _buildURL(url) {
    console.log(url);
  }

  // Overriding inherit method
  parse(value) {
    // Using super to call parent method
    console.log("Overring method: " + super.parse(this.name));
  }

  render() {
    let link = this._buildURL(this.url);

    // Calling inherit property and method
    this.parse(this.baseCSS);
  }
}

Thursday, December 22, 2016

JavaScript Evolution ECMAScript 6 - Sets

Before we understand the needs to use Sets, let's go back to understand Array limitation.

Array in JavaScript is very simple to use, but 1 thing they don't do is Array doesn't enforce uniqueness of items. Duplicate entries are allowed.
let tags = [];
tags.push ("JavaScript");
tags.push("Programming");
tags.push("Web");
tags.push("Web");

console.log(tags.length); // Return 4
If we want to prevent duplicate entry to be added into a collection, instead of Array, we can use Set. Set object stores uniques values of any types, where primitives values or object references.
let tags = new Set();
tags.add("JavaScript");
tags.add("Programming");
tags.add({version: "2015"}); // We can add object
tags.add("Web");
tags.add("Web"); // Duplicate entry are ignored.

console.log(tags.size); // Return 4
Set object is iterative, which means they can be used with for...of and destructuring.
for (let tag of tags) {
  console.log(tag);
}

// Return:
// JavaScript
// Programming
// {version: "2015"}
// Web

let [a, b,c, d] = tags;
console.log(a ,b, c, d);

// Return JavaScript, Programming, {version: "2015"}, Web

JavaScript Evolution ECMAScript 6 - WeakMap (Better with Memory with Limitation)

WeakMap is a type of Map where only Objects can be passed as keys. Primitive data types such as String, Number, Boolean, etc are not allowed.
let user = {};
let comment = {};

let mapSettings = new WeakMap();
mapSettings.set(user, "Sam");
mapSettings.set(comment, "Great Post!!!");

console.log(mapSettings.get(user)); // Return Sam
console.log(mapSettings.get(comment)); // Return Great Post!!!
You can't assign primitive data types as key.
let mapSettings = new WeakMap();
mapSettings.set("user", "Sam"); // Return Error - Invalid value used as weak map key
Other methods available are has() and delete().
console.log(mapSettings.has(user)); // Return true
console.log(mapSettings.delete(user)); // Return true
WeakMap is not iterable, therefore they can't be used with for...of.

JavaScript Evolution ECMAScript 6 - Maps

Maps are a data structure composed of a collection of key/value pairs. they are very useful to store simple data such as property value. They are present in many programming languages such a Scala.

The key in Map must be unique and associated with only 1 value.

key ---> value
key ---> value
key ---> value

JavaScript developer explores to Map thru Object. It is possible to use Object as Map, but there is some issue with that. The biggest issue of using Object as Map is the key always converted to String.

Let's take a look at the below example:
let user1 = {name: "Sam"};
let user2 = {name: "Tyler"};

let totalReplies = {};
totalReplies [user1] = 5;
totalReplies [user2] = 42;

console.log(totalReplies [user1]); // Return 42
console.log(totalReplies [user2]); // Return 42
Although we assign 2 different value to the key, the last assign overwrites the previous value because JavaScript converts the Object to String - [object, object].

To get around this issue, we should use the Map. Any value may be used as either a key or a value are not converted to String. Let change totalReplied to a Map.
let user1 = {name: "Sam"};
let user2 = {name: "Tyler"};

let totalReplies = new Map();
totalReplies.set(user1, 5);
totalReplies.set(user2, 42);

console.log(totalReplies.get(user1)); // Return 5
console.log(totalReplies.get(user2)); // Return 42
As you can see, the 2 value assigned to different Object key as expected.

We use get() and set() methods to access the value in Map. To delete a value in Map, you can use delete() method.
totalReplies.delete(user1);
The map is iteratable, so they can be used in the for...of loop. Each ran of the loop returns a [key, value] pair for an entry in the Map.
let mapSettings = new Map();
mapSettings.set("user", "Sam");
mapSettings.set("topic", "ES2015");

for (let [key, value] of mapSettings) {
  console.log(`${key} = ${value}`);
}

// Return
// user = Sam
// topic = ES2015

JavaScript Evolution ECMAScript 6 - New Additional to Array

Assigning From Array to Local Variables

Typically we access array elements using index.
let users = ["Sam", "Tyler", "Brook"];
let a = users[0];
let b = users[1];
let c = users[2];
In ES2015, new implement in Array destructuring allows us to write less code.
let users = ["Sam", "Tyler", "Brook"];
let [a, b, c] = users;
If there is any value that not interested in, we can discard.
let users = ["Sam", "Tyler", "Brook"];
let [a, ,b] = users;
We can combine destructuring with rest parameters to group values into other Array.
let users = ["Sam", "Tyler", "Brook"];
let [first, ...rest] = users;
console.log(first); // Return "Sam".
console.log(rest); // Return a new Array ["Tyler", "Brook"]

Using for...of to loop over Array

The for...of statement iterates over property values, and it's a better way to loop over arrays and other iterate objects.

Here is the typical way we loop thru array using index.
let names = ["Sam", "Tyler", "Brook"];
for (let index in names) {
  console.log (names[index]);
}
Now, using for...of, we don't use the index.
let names = ["Sam", "Tyler", "Brook"];
for (let name of names) {
  console.log(name);
}

Finding an Element in an Array

Array find returns the first element in the Array that satisfies a provided testing function.
let users = [
  {login: "Sam", admin: false},
  {login: "Brook", admin: true},
  {login: "Tyler", admin: true}
];
let admin = users.find( (user) => {
  return user.admin;
});
console.log(admin); // Return {login: "Brook", admin: true}

Tuesday, December 20, 2016

JavaScript Evolution ECMAScript 6 - Merging Object via Object.assign()

Copying all properties of one object to another one is a common operation in JavaScript. In this article, we gonna explore ES2015 new implementation of Object.assign().

Object.assign() syntax is Object.assign(target, sources, ...). The target object is the return value and the source is the object to be copied.

Example of merging an object:
let first = {first: "Sam"};
let last = {last: "Wong"};
let person = Object.assign(first, last);
console.log(person); // Return {first: "Sam", last: "Wong"}
console.log(first); // Return {first: "Sam", last: "Wong"} as the source also changed.
Example of merging an object without modifying the source (cloning)
let first = {first: "Sam"};
let last = {last: "Wong"};
let person = Object.assign({}, first, last);
console.log(person); // Return {first: "Sam", last: "Wong"}
console.log(first); // Return {first: "Sam"} as source's value preserve
Example of merge multi-source and value is overwritten when the key is equal.
let b = Object.assign({foo:0},{foo:1},{foo:2});
console.log(b); // Return {foo:2} as last object prevail.
In use-case, Object.assign() is practical to write flexible and usable function. In the coming example, we are going to write a buildUser function which accepts 2 parameters (first, last), and a custom Options (lettercase, and targetElement) will vary according to each call of the function. The function can be called in many ways.
buildUser("Sam", "Wong");
buildUser("Sam, "Wong", {lettercase: "upper"});
buildUser("Sam", "Wong", {lettercase: "upper", targetElement: ".username"})
For such function, it is okay to accept the object parameter instead using the name parameter.

Example of Name Parameter:
// Bad implementation as not easy to read when scale to more arguments.
function buildUser(first, last, {lettercase, targetElement} = {})
Example of Object Parameter:
// Good implement as easy to read when scale.
function buildUser(first, last, options = {})
Some options might not be specified by the caller, so we need to have default values. One way we can do it by using ||. This code worked, the issue here is the default value can be anywhere which is hard to read.
function buildUser (first, last, options = {}){
  let lettercase = options.lettercase || "uppercase";
  let targetElement = options.targetElement || ".username";
  ...
}
To solve this, we group default values in 1 place. The grouping default value is the common pattern in a large project. It can help us write more idiomatic JavaScript. The next step is to merge the default and options using the Object.assign() syntax. The important point is options value must overwrite default value and the result stores in setting variable.
function buildUser(first, last, options = {}) {
  let defaults = {
    lettercase = "upper",
    targetElement = ".username"
  }

  let setting = Object.assign({}, defaults, options);
  console.log(setting.lettercase);
  console.log(setting.targetElement);
}

JavaScript Evolution ECMAScript 6 - Template String

Template String is string literals allowing embedded expressions.

Below is the typical way we assign a text into a variable.
function buildUser(first, last) {
  let fullname = first + " " + last;
  ...
}
In ES2015, we can wrap the entitled text with backtick `. Any JavaScript need to be evaluated inside the backtick, wrap it with ${...}.
function buildUser(first, last) {
  let fullname = '${first} ${last}';
  ...
}
Template String offers a new and much better way to write multiple strings.
let longText = ' Hi ${username}
This is a very
veeery
long text.

Regards,
  ${admin.fullname}
`;

// Newline characters is preserve and output to screen.
console.log(longText);

JavaScript Evolution ECMAScript 6 - Simplified Object

Removing Repetition Object

Here is the typical way we write a return object function.
function buildUser(first, last) {
  let fullname = first + " " + last;
  return {first : first, last : last, fullname : fullname};
}
The returned object with keys and variables with the same name is repetitive. We can remove duplicate variables names from object properties when those properties have the same name as the variables being assigned to them.
function buildUser(first, last) {
  let fullname = first + " " + last;
  return {first, last, fullname};
}
This simplicity called Object Initializer Shorthand.

Object Initializer Shorthand can works anywhere, as long as a new object is returned, not just from function.
let first = "Sam";
let last = "Wong";
let userOld = {first : first, last : last};
let userNew = {first, last}; // Simplified

Object Destructing 

Let's look at another side of reading properties from an object.

Here is the typical way we read properties from an object.
let user = buildUser("Sam", "Wong");
let first = user.first;
let last = user.last;
let fullname = user.fullname;
In ES2015, we can read an object's properties using simplified syntax.
let {first, last, fullname} = buildUser("Sam", "Wong");
console.log(first);
console.log(last);
console.log(fullname);
We can read as well as subset return function properties. Below example, we just want to grab the fullname and leave first, last out.
let {fullname} =  buildUser("Sam", "Wong");;
console.log(fullname);

Method Initializer Shorthand

Here is the typical way we write method in function object.
function buildUser(first, last, age) {
  let fullname = first + " " + last;
  const AGE_LIMIT = 18;
  return {
    first,
    last,
    fullname,
    isAgeOverLimit : function () {
      return age >= AGE_LIMIT;
    }
  }
}
With method initializer shorthand, we can simplify by removing the function ().
function buildUser(first, last, age) {
  let fullname = first + " " + last;
  const AGE_LIMIT = 18;
  return {
    first,
    last,
    fullname,
    // Less character and easier to read.
    isAgeOverLimit () {
      return age >= AGE_LIMIT;
    }
  }
}

Monday, December 5, 2016

JavaScript Evolution ECMAScript 6 - Function with Rest Parameter

JavaScript functions have a built-in object called the argument object. The argument object contains an array of the argument used when the function is called. This kind of function called variadic function.
x = displayTags("A","B","C");
function displayTags() {
  for (let i in arguments){
    let tag = arguments[i];
    addTagTopic(tag);
  }
}
The variadic function gives a major problem where we add an argument, its break our code.
x = displayTags("A","B","C");
function displayTags(targetElement) {   let target = findElement(targetElement);   for (let i in arguments){     let tag = arguments[i]; // Break since the last argument it is no longer a tag.     addTagTopic(tag);   } }
The new rest parameter syntax allows us to represent an indefinite number of arguments as an Array. This way, changes to function signature are less likely to break the code.
function displayTags(...tags) {
  for (let i in tags){
    let tag = tags[i];
    addTagTopic(tag);
  }
}
// Rest parameter must go last.
function displayTags(targetElement, ...tags) {
  let target = findElement(targetElement);
  for (let i in tags){
    let tag = tags[i];
    addTagTopic(tag);
  }
}

JavaScript Evolution ECMAScript 6 - Function with Default Parameter

In ES2015, a developer can add a default parameter into a function. Example:
function loadProfile(usernames=[]){
  if (usernames.lenght > 3){
    let loadingMessage ="This will take a while.";
  }
}
With default parameter, you can call the function either
loadProfile(['Simon','Alex','Arlene']);
Or
loadProfile();
Scala has more powerful default parameter. Let's create Scala function with default parameter.
def addInt(a:Int=5, b:Int=7) = {
  var sum: Int = a + b;
  return sum
}
You can call the function by passing the parameter using a pointer.
addInt(b=10)
Passing parameter using pointer is not implement in JavaScript.

JavaScript Evolution ECMAScript 6 - Using let and const

Prior executing code, JavaScript moves var declarations all the way up to the top of the scope. This is known as a hoist. Example:
function loadProfile(usernames) {
  if(usernames.lenght > 3) {
    var loadingMessage = "This will take a while";
  }
}
JavaScript runtime transform to
function loadProfile(usernames) {
  var loadingMessage;
  if(usernames.lenght > 3) {
    loadingMessage = "This will take a while";
  }
}
This explained developer can access the variable outside the block. Example:
function loadProfile(usernames){
  if(usernames.length > 3) {
    var loadingMessage = "This will take a while";
  }
  consolo.log (loadingMessage );
  // Output is unexpected - can be "This will take a while" or undefined.
}
var variable can be accessed in entitled function which might cause unexpected behaviour. One way you can avoid this by introducing a new variable declaration let.

let variables are scoped to the nested block and are Not hoisted. Block is any code section within curly braces like if, else, while, etc. Example:
function loadProfile(usernames) {
  if (usernames.length > 3) {
    let loadingMessage ="This might take a while";
  }
  consolo.log(loadingMessage);
  // Output is ReferencesError: loadingMessage is not defined.
}
Variables declared with let can be reassigned, but cannot be redeclared within the same scope.
let loadingMessage = "Hello";
loadingMessage = "Goodbye"; // Reassigning is allowed.
let loadingMessage = "Hello";
let loadingMessage = "Goodbye";
// Re declaring is not allowed.
// TypeError: Identified 'loadingMessage' has already been declared.
Second type of new variable is const. const keyword created read-only named constant. Example
const MAX_USERS = 3;
Constant cannot be reassigned. Example:
const MAX_USERS = 3;
MAX_USERS = 10; // Error
Constant must be assigned an initial value. Example:
const MAX_USERS = 3; // No error.
const MAX_USERS;
MAX_USERS = 3; // Error
Constant are scoped to the nearest block, same to let.

Monday, November 28, 2016

Angular 2 Part 5.3 - HTTP

In part 5.3, we are going to fetch our data using HTTP JSON call instead of mock data.

There are 5 steps to make it happen:

1. Create a JSON data file to simulate the data from the server - car-parts.json.
{
 "data" : [
  {
   "id":1,
   "name":"Super Tires",
   "price":2.0,
   "description":"These tires are the very best",
   "inStock":5,
   "image":"/images/example1.png",
   "featured":false,
   "quantity":0
  },
  {
   "id":2,
   "name":"Reinforced shocks",
   "price":4.99,
   "description":"Shock made from krytonite",
   "inStock":4,
   "image":"/images/example2.png",
   "featured":true,
   "quantity":0
  },
  {
   "id":3,
   "name":"Padded Seats",
   "price":2,
   "description":"Super soft scats for a smooth ride.",
   "inStock":0,
   "image":"/images/example3.png",
   "featured":false,
   "quantity":0
  }
 ]
}

2. We need to include HTTP and RxJS Libraries. The HTTP library provides the get call we will use to call across the internet. The RxJS library stands for Reactive Extensions and provides some advance tooling for our HTTP Calls. If you used the 5 minutes QuickStart, you have already included these libraries using systemjs.config.js.

3. Import HTTPModule in main.ts. We can skip adding HTTP as provider because it had already added in HTTPModule.
import {NgModule, Component} from '@angular/core';
import {AppComponent} from './app.component';
import {CarPartComponent} from './car-parts.component';
import {BrowserModule} from '@angular/platform-browser';
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import { RacingDataService } from './racing-data.service';
import { HttpModule } from '@angular/http';
import { FormsModule } from '@angular/forms';

@NgModule ({
  imports:      [ BrowserModule, FormsModule, HttpModule ], // List down all component will be used.
  declarations: [ AppComponent, CarPartComponent ], // Import dependencies.
  bootstrap:    [ AppComponent ], // Indicate first component to launch.
  providers:  [ RacingDataService ] // Now all subcomponents can ask for (inject) our RacingDataService.
})

class AppModule {}

// Start the application in web browser.
platformBrowserDynamic().bootstrapModule(AppModule);
4. Now we can inject HTTP and using it in racing-data.service.ts.
import { CARPARTS } from './mocks';
import {CarPart} from './car-part';
import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class RacingDataService {

 constructor(private http: Http) {}

 getCarParts() {
  return this.http.get('app/car-parts.json')
   .map(response => <CarPart[]>response.json().data);
 }

}
response = data returned.
<CarPart[]> = Tells our TypeScript compiler to treat this like an arrays of CarPart.
response.json() = For each response, parse the string into JSON.
.data = The array we want is under the data keyword.

5. Since our service returns an observable, we need to subscribe to that data stream and tell our component what to do when our data arrives.
import {Component} from '@angular/core';
import {CarPart} from './car-part';
import { RacingDataService } from './racing-data.service';

@Component({
  selector: "car-parts", // Display in selector defined in app.component.ts
  templateUrl: "app/car-parts.component.html",
  styleUrls: ["app/car-parts.component.css"]
})

export class CarPartComponent {
  carParts : CarPart[];

  // Declare a constructor
  constructor (private racingDataService: RacingDataService) {}

  ngOnInit() {
    this.racingDataService.getCarParts()
      .subscribe(carParts => this.carParts = carParts); // When carParts arrive on our data stream, set it equal to our local carParts array.
  }

  totalCarParts(){
    let sum = 0;
      if(Array.isArray(this.carParts)) {
        for (let carPart of this.carParts) {
          sum += carPart.inStock;
        }
      };
    return sum;
  }

  upQuality(carPart){
    if (carPart.quantity < carPart.inStock) carPart.quantity++;
  }
 
  downQuality(carPart){
    if (carPart.quantity != 0) carPart.quantity--;
  }

}

That's all for Angular 2 sample and I hope you all enjoyed. Here are some tools you might interest.

  • Angualr Angury an Angular 2 debugging tool.
  • Angular CLI - Angular Command Line Interface for developer kicks start project really fast.
Download Car Part Source:
https://github.com/htsiah/angular2-carparts

Angular 2 Part 5.2 - Service using Dependency Injector

In Part 5.1, we introduced the simplest way to create service. However, this is yet a best solution because we need to create new RacingDataService every time when we need to fetch the data. This would used up more memory.

This is where dependency injection come in. When you run Angular 2 application, it creates a dependency injector. An injector is in charge of knowing how to create and send things.

One of the advantages is that dependency injection know how to resend the same service if the injector already created a service.

There are 3 steps to make all work in our example:

1. Add the injectable decorator to racing-data.service.ts.
...
import { Injectable } from '@angular/core';

@injectable()
...

2. Let our injector know about our service by naming it as a provider in main.ts
@NgModule ({
  imports:      [ BrowserModule, FormsModule, HttpModule ], // List down all component will be used.
  declarations: [ AppComponent, CarPartComponent ], // Import dependencies.
  bootstrap:    [ AppComponent ], // Indicate first component to launch.
  providers:  [ RacingDataService ] // Now all subcomponents can ask for (inject) our RacingDataService.
})

3. Inject the dependency into our car-parts.component.ts
export class CarPartComponent {
  carParts : CarPart[];

  // Declare a constructor
  constructor (private racingDataService: RacingDataService) {}

  ngOnInit() {
    this.racingDataService.getCarParts()
  }

  ...
}

Now our application is more scalable because our dependencies aren't strongly tied our classes.

Download Car Part Source:
https://github.com/htsiah/angular2-carparts

Angular 2 Part 5.1 - Service

Service is used to organize and share code across your app, and they's re usually where you create your data access.

In our car part example, we are using mock file for data loading. Actually this is not a very good solution because we need to import mock in every file that need the data. Also, it is not easy to switch between real and mock data. This sort of data loading is best left to service classes.

Let create the simplest service by creating racing-data.services.ts. The flow will be car-parts.component.ts -> racing-data.services.ts -> mock.ts.

Here is our racing-data.services.ts:
import { CARPARTS } from './mocks';

export class RacingDataService {

 getCarParts() {
  return CARPARTS ;
 }
}

Our car-part.component.ts will lookup the new created racing-data.service.ts instead of mock.ts.
...
import { RacingDataService } from './racing-data.service';
...

export class CarPartComponent {
  ...
  ngOnInit() {
   let racingDataService = new RacingDataService();
   this.racingDataService.getCarParts()
  }
  ...
}

Download Car Part Source:
https://github.com/htsiah/angular2-carparts

Angular 2 Part 4.3 - Two-way Binding

In Part 4.3, I am going to introduce two-way binding where value keeps in sync in Javascript and HTML.

In our car part example, I am going to add a text field for quantity. User can fill up a quantity or click on plus / minus button to purchase. The value in the text field and buttons is in sync.

...
<input type="text" [(ngModel)]="carPart.quantity">
...
We import FormsModule in main.ts.

...
import { FormsModule } from '@angular/forms';

@NgModule ({
  imports:      [ BrowserModule, FormsModule], // List down all component will be used.
  declarations: [ AppComponent, CarPartComponent], // Import dependencies.
  bootstrap:    [ AppComponent ], // Indicate first component to launch.
  providers:  [RacingDataService] // Now all subcomponents can ask for (inject) our RacingDataService.
})
...

ngModel allows having one command to express two-way data binding. The syntax for two-way binding is [()], and sometimes called banana in a box.

Important to know when we are using ngModel syntax, we only set it equal to a data properly. Example:

[(ngModel)] = "user.age"
[(ngModel)] = "firstname"

You can not set ngModel to a component's method. Example:

[(ngModel)] = "fullname()"

Two-way binding means that if the component property is modified inside the component (Javascript) or inside our web page (HTML), it will stay in sync.

To summary on binding syntax:
  • [] - JavaScript to HTML binding
  • () - HTML to Javascript binding
  • [()] - Two-way binding binding.

Tuesday, November 22, 2016

Angular 2 Part 4.2 - Event Binding

In Part 4.1, I covered Property Binding and Class Binding. Both is JavaScript to HTML data flow.

In Part 4.2, I am going to introduce Event Binding which is HTML to JavaScript data flow. Any standard DOM Event can be listened for by wrapping it in parentheses and removing the "on" at the beginning of the word. Example:
  • <div (mouseover)="call()">
  • <input (blur)="call()">
  • <input (focus)="call()">
  • <input type="text" (keydown)="call()">
  • <form (submit)="call()">
Sometime, you need additional event data like which key is pressed or where the mouse is on the screen. We can pass it in to our component method with $event. Example:
<input type="text" (keydown)="showKey($event)">

showKey(event){
  //Prompt on key is pressed
  alert(event.keycode); 
}
<h2 (mouseover)="getCoord($event)">Hover Me</h2>

getCoord(event){
  // Display mouse X and Y coordinate.
  consolo.log(event.clientx + ", " + event.clienty);
}
I am going to add plus and minus button and bind this 2 buttons into a method in our car part example.

We add quantity property into our model.
export class CarPart {
  ...
  quantity:number;
}
Add quantity data into mock.ts.
export const CARPARTS : CarPart[] = [{ 
  "id":1,
  ...
  "quantity":0
},
{
  "id":2,
  ...
  "quantity":0
},
{
  "id":3,
  ...
  "quantity":0
}] // Example of object
Add 2 methods into car-parts.component.ts.
export class CarPartComponent {
  carParts : CarPart[];
  ngOnInit() {
    this.carParts = CARPARTS;
  }

  totalCarParts(){
    let sum = 0;
    for (let carPart of this.carParts) {      sum += carPart.inStock;
    }
    return sum;
  }

  upQuality(carPart){
    if (carPart.quantity < carPart.inStock) carPart.quantity++;
  }

  downQuality(carPart){
    if (carPart.quantity != 0) carPart.quantity--;
  }
}
Add 2 buttons into car-parts.component.html and bind to our created methods on click event.
<li *ngFor="let carPart of carParts" [class.featured]="carPart.featured">
  <h2>{{carPart.name | uppercase}}</h2>
    <img [src]="carPart.image">
    <p class="description">{{carPart.description}}</p>
    <p class="price">{{carPart.price | currency:"EUR":true}}</p>
    <p *ngIf="carPart.inStock > 0">{{carPart.inStock}} in stock</p>
    <p *ngIf="carPart.inStock === 0">Out of stock</p>
    <p><button (click)="downQuality(carPart)">-</button> {{carPart.quantity}} <button (click)="upQuality(carPart)">+</button></p>
</li>
Here is out put:




















Download Car Part Source:
https://github.com/htsiah/angular2-carparts

Angular 2 Part 4.1 - Property and Class Binding

In Part 4, we are going to demonstrate binding in Angular. There are 3 different ways that data can flow (bind):
  1. JavaScript to HTML - Like we have been doing with property from our components.
  2. HTML to JavaScript - Like a mouse click, hover or key press.
  3. Both way - Like a text box that should stay in sync.
First, let me introduce Property Binding by adding an image. Property binding allows us to bind Component Properties to any DOM Element Properties. What we need to do is add [] into the DOM Element Properties. Any update to the Component Property value will update the DOM Property, but not vise versa - that's why it's "One way binding".

We add an image property into our model.
export class CarPart {
  id:number;
  name:String;
  price: number;
  description:String;
  inStock:number;
  image:String;
}
In our mocks.ts, we add image data.
export const CARPARTS : CarPart[] = [{ 
  "id":1,
  "name":"Super Tires",
  "price":2.0,
  "description":"These tires are the very best",
  "inStock":5,
  "image":"/images/example1.jpg"
},
{
  "id":2,
  "name":"Reinforced shocks",
  "price":4.99,
  "description":"Shock made from krytonite",
  "inStock":4,
  "image":"/images/example2.jpg"
},
{
  "id":3,
  "name":"Padded Seats",
  "price":2,
  "description":"Super soft scats for a smooth ride.",
  "inStock":0,
  "image":"/images/example3.jpg"
}] // Example of object
Here we add our images into car-parts.component.html.
<li *ngFor="let carPart of carParts">
  <h2>{{carPart.name | uppercase}}</h2>
  <img [src]="carPart.image">
  <p class="description">{{carPart.description}}</p>
  <p class="price">{{carPart.price | currency:"EUR":true}}</p>
  <p *ngIf="carPart.inStock > 0">{{carPart.inStock}} in stock</p>
  <p *ngIf="carPart.inStock === 0">Out of stock</p>
</li>
Here are the additional Property Binding example:
  • <div [hidden]="!user.isAdmin">Secret</div>
  • <button [disable]="isDisabled">Purchase</button>
  • <img [alt]="image.description">
Next, I am going to introduce Class Binding by adding CSS Class on featured product. Class Binding allows us to specify a CSS Class to add to a DOM Element if a Component Property is True.

We add a featured property into our model.
export class CarPart {
  id:number;
  name:String;
  price: number;
  description:String;
  inStock:number;
  image:String;
  featured:boolean;
}
In our mocks.ts, we add feature data. Only 1 product is featured.
export const CARPARTS : CarPart[] = [{ 
  "id":1,
  ...
  "featured":false
},
{
  "id":2,
  ...
  "featured":true
},
{
  "id":3,
  ...
  "featured":false
}] // Example of object
In our car-parts.component.css, we add featured class.
.featured{
  border: 1px solid black;
}
Here we add our feature CSS Class into car-parts.component.html.
<li *ngFor="let carPart of carParts" [class.featured]="carPart.featured">
  <h2>{{carPart.name | uppercase}}</h2>
  <img [src]="carPart.image">
  <p class="description">{{carPart.description}}</p>
  <p class="price">{{carPart.price | currency:"EUR":true}}</p>
  <p *ngIf="carPart.inStock > 0">{{carPart.inStock}} in stock</p>  <p *ngIf="carPart.inStock === 0">Out of stock</p>
</li>
Here is the output where featured product's has border.




















If carPart.featured is true, then featured class is added.

If carPart.featured is false, then featured class is removed.

The format for Class Binding is [class.'name if the CSS Class'] = Component Property.

To overwrite the whole class, you can use this format ['name if the CSS Class'] = Component Property.

Download Car Part Source:
https://github.com/htsiah/angular2-carparts

Angular 2 Part 3.3 - Model & Mock

In TypeScript, we can use classes to model our data. This helps us specify class property types that help our compiler ensure we're writing good code. I am going to model our car part by creating car-part.ts.

car-parts.ts
export class CarPart {
  id:number;
  name:String;
  price: number;
  description:String;
  inStock:number;
}
Mock is to separate our data file from component. It is good practice to keep our mock data separate from our model and component. I am going to move our data to mock.ts.

mock.ts
import {CarPart} from './car-part';

export const CARPARTS : CarPart[] = [{ 
  "id":1,
  "name":"Super Tires",
  "price":2.0,
  "description":"These tires are the very best",
  "inStock":5
},
{
  "id":2,
  "name":"Reinforced shocks",
  "price":4.99,
  "description":"Shock made from krytonite",
  "inStock":4
},
{
  "id":3,
  "name":"Padded Seats",
  "price":2,
  "description":"Super soft scats for a smooth ride.",
  "inStock":0
}] // Example of object
Now we going to integrate car-parts.ts and mock.ts into our car-parts.component.ts.
import {Component} from '@angular/core';
import {CarPart} from './car-part';
import {CARPARTS} from './mocks';

@Component({
  selector: "car-parts", // Display in selector defined in app.component.ts
  templateUrl: "app/car-parts.component.html",
  styleUrls: ["app/car-parts.component.css"]
})

export class CarPartComponent {  
  carParts : CarPart[];

  ngOnInit() {
    this.carParts = CARPARTS;
  }

  totalCarParts(){
    let sum = 0;
    for (let carPart of this.carParts) {
      sum += carPart.inStock;
    }
    return sum;
  }
}
ngOnInit() is invoked after the component is constructed and is the best place to initialize properly value.

For whole Part 3, we don't add any new functionality, but our code now is more easy to maintenance and scale. Let's look at our files structure.

  • index.html - Include <my-app> and load main.ts.
  • app\main.ts - Import and bootstraps our first component in app.component.ts.
  • app\app.component.ts - Load the header and sub component in car-parts.component.ts.
  • app\car-parts.component.ts - Our JavaScript.
  • app\car-part.ts - The data model.
  • app\mocks.ts - The fake data.
  • app\car-parts.component.html
  • app\car-parts.component.css
Download Car Part Source:

Monday, November 21, 2016

Angular 2 Part 3.2 - Component HTML & CSS

Our application does not look nice without CSS decoration. I am going to add CSS into our component decorator by introduce styles.

@Component({
  selector: "car-parts", // Display in selector defined in app.component.ts
  template: `
    <p>There are {{totalCarParts()}} total parts in stock.</p>
    <ul>
      <!-- carParts in an array object defined in AppComponent Class. -->
      <!-- carPart is a local variable. -->
      <li *ngFor="let carPart of carParts">
        <h2>{{carPart.name | uppercase}}</h2>
        <p class="description">{{carPart.description}}</p>
        <p class="price">{{carPart.price | currency:"EUR":true}}</p>
        <p *ngIf="carPart.inStock > 0">{{carPart.inStock}} in stock</p>
        <p *ngIf="carPart.inStock === 0">Out of stock</p>
      </li>
    </ul>
  `,
  styles: [`
    .description { 
      color: #ff0000;
      font-size: small;
    }
    .price{
      font-weight: bold;
    }
  `]
})

Here is out put.





















Can we have same CSS Class Name in different component in same page? Answer is Yes, because Angular scope the CSS Class. Confusing? Try to create same Class Name in different component in same page and view browser's source, you should understand.

Huh... Now we have JavaScript, HTML and CSS in same file. Is it messy and hard to maintenance when scale? Let's split our HTML and CSS into different file by using component decorator templateUrl and styleUrls. HTML will store in car-parts.component.html and CSS will store in car-parts.component.css.

car-parts.component.html
<p>There are {{totalCarParts()}} total parts in stock.</p>
<ul>
  <!-- carParts in an array object defined in AppComponent Class. -->
  <!-- carPart is a local variable. -->
  <li *ngFor="let carPart of carParts">
    <h2>{{carPart.name | uppercase}}</h2>
    <p class="description">{{carPart.description}}</p>
    <p class="price">{{carPart.price | currency:"EUR":true}}</p>
    <p *ngIf="carPart.inStock > 0">{{carPart.inStock}} in stock</p>
    <p *ngIf="carPart.inStock === 0">Out of stock</p>
  </li>
</ul>
car-parts.component.css
.description {
  color: #ff0000;
  font-size: small;
}

.price{
  font-weight: bold;
}
car-parts.component.ts
@Component({
  selector: "car-parts", // Display in selector defined in app.component.ts
  templateUrl: "app/car-parts.component.html",
  styleUrls: ["app/car-parts.component.css"]
})
Again, no new functionality, just splitting the files.

Download Car Part Source:
https://github.com/htsiah/angular2-carparts