Showing posts with label angular2. Show all posts
Showing posts with label angular2. Show all posts

3/21/17

Angular2 and NgRx

My Challenge was to get little experience of working with ngrx .
What is NgRx?
NgRx is RxJS powered, inspired by Redux state management lib for Angular2.

Basic Philosophy

Like many state management frameworks like Redux - app skeleton must include following module types - Store, Actions and Reducers

Store

simple class or object representing the application state


import postListReducer, * as fromPostList from './post-list';
import postReducer, * as fromPost from './post';

export interface AppState {
    posts: fromPostList.PostListState;
    post: fromPost.PostState;
};

Actions

function that passes type and params of what reducer should do


    static LOAD_POSTS = '[Post] Load Posts';
    loadPosts(): Action {        
        return {
            type: PostActions.LOAD_POSTS
        };
    }

Reducers

Immutable function that returns new object containing changed current state returned


export default function (state = initialState, action: Action): PostListState {
    switch (action.type) {
        case PostActions.LOAD_POST_SUCCESS: {            
            return action.payload;
        }
    }
}

Effects

Since state actions are asynchronous - it is better to take advantage of using effects:


    @Effect() loadPosts$ = this.update$
        .ofType(PostActions.LOAD_POSTS)
        .switchMap(() => {            
            return this.svc.getAllSections();
        })
        .map(posts => this.postActions.loadPostsSuccess(posts));

Refactoring our components

Now we can replace our logic inside components:
Instead of:


   this.loadHtml.getPost(params['id']).subscribe(post => {
        this.post = post;
      })

We can now write:

  this.store.dispatch(this.postActions.getPOST(this.name));
  ...
  ...
   store.select('post').subscribe((post:Post) => {
     this.post = post;   
  })

Much more accurate, is it?

3/9/17

Learning Angular2 - Free Stuff

Hi my dear readers, hope you all well...
Wanted to publish some interesting post about angular2 form validations.
Template driven forms VS reactive forms, NgModel, NgForm etc... You know

But instead i decided it will be more useful to publish links to some angular2 tutorials/ blogs i gathered across internet:

Free online Books:
Free video tutorials:
Blogs
Github Repos


Thats not a lot, but pretty angouth to start with...
Anyway feel free to add more free useful stuff in the comments!
   

    

2/2/17

Using Angular2 Components Inside Angular1 Project

Dreaming About Upgrade

If you working on project that built with angular1 for historical reasons and dreaming about move to angular2 - this article is for you.
Yes, it is possible to move to angular2 make little changes step by step, without breaking the running code of your application. In this article i will take this angular-seed repo and try to make it run with some angular2 component included.

Step 1 - Bootstrap Angular Different Way

Usually the angular is attached to HTML using ng-app directive but there is another way to bootstrap angular to your application - using angular.bootstrap utility:


angular.bootstrap(document.body, ['myApp'], {strictDi: true});

You can view source at this branch

Step 2 - Migrating to Typescript

To move project to typescript you need :
1. rename all the files to end with ts instead of js (meanwhile leave files finishing with 'test' and not rename them to ts)
2. install typescript compiler:

npm i typescript -D
3.create tsconfig.json file at root directory

{
  "compilerOptions": {
    "target": "es5",
    "module": "commonjs",
    "moduleResolution": "node",
    "sourceMap": true,
    "emitDecoratorMetadata": true,
    "experimentalDecorators": true,
    "removeComments": false,
    "noImplicitAny": false,
    "suppressImplicitAnyIndexErrors": true
  }
}

4. install type definitions for angular and other dependencies
npm install @types/angular -D
If all the installations succeed - after running
tsc -p .
command all ts files should have their ".js" and "map.js" copies - appear near them.


You can view source at this branch

Step 3 - Move application to load dependencies from node modules

Why? Mostly from reason that angular2 recommend to load dependencies this way instead of using bower. So, since node_modules directory located at project root we need to modify index.html so all the urls will stay correct:
Insert base tag inside head tag of your index.html


<base href="/app/">

Also you will need to change "start" script inside package.json:

"start": "http-server -a localhost -p 8000 -c-1 ./",

Now you can install all the dependencies like angular through NPM:

    "angular": "^1.6.1",
    "angular-route":"^1.6.1",

Don't forget to change the paths inside the index.html:

  <script src="/node_modules/angular/angular.js"></script>
  <script src="/node_modules/angular-route/angular-route.js"></script>

Now make sure that after you run
tsc -p ./
and then:
npm start
command you can see the project running:

You can view the full code on this branch

Step 4 - Install Systemjs Module Loader

Module Loader - a way to make javascript to import or export different javascript types (like classes) from one file to other. There are several javascript module loaders such as Webpack, Browserify, Systemjs - for our tutorial we will use systemjs.

npm install systemjs -D
After installation lets try to include the systems script to "index" page:

  <script src="/node_modules/systemjs/dist/system.src.js"></script>

Important: systemsjs uses its own configuration file - systems.config You may place it in the "app" directory:


/**
 * System configuration for Angular samples
 * Adjust as necessary for your application needs.
 */
(function (global) {
  System.config({
    paths: {
      // paths serve as alias
      'npm:': '/node_modules/'
    },
    // map tells the System loader where to look for things
    map: {
      // our app is within the app folder
      app: '/app',

      // angular bundles
      '@angular/core': 'npm:@angular/core/bundles/core.umd.js',
      '@angular/common': 'npm:@angular/common/bundles/common.umd.js',
      '@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
      '@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
      '@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
      '@angular/http': 'npm:@angular/http/bundles/http.umd.js',
      '@angular/router': 'npm:@angular/router/bundles/router.umd.js',
      '@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',      
      '@angular/upgrade/static':'npm:@angular/upgrade/bundles/upgrade-static.umd.js',
      // other libraries
      'rxjs':                      'npm:rxjs',
      'angular-in-memory-web-api': 'npm:angular-in-memory-web-api/bundles/in-memory-web-api.umd.js'
    },
    // packages tells the System loader how to load when no filename and/or no extension
    packages: {
      app: {
        main: './main.js',
        defaultExtension: 'js'
      },
      rxjs: {
        defaultExtension: 'js'
      }
    }
  });
})(this);

This files points to system module loader where the scripts located. Lets see if it loaded now in the chrome developer tools:
After we can see everything is still working lets add angular2 dependencies to package.json:

    "@angular/common": "~2.4.0",
    "@angular/compiler": "~2.4.0",
    "@angular/core": "~2.4.0",
    "@angular/forms": "~2.4.0",
    "@angular/http": "~2.4.0",
    "@angular/platform-browser": "~2.4.0",
    "@angular/platform-browser-dynamic": "~2.4.0",
    "@angular/router": "~3.4.0",

    "angular-in-memory-web-api": "~0.2.4",
    "systemjs": "^0.20.4",
    "core-js": "^2.4.1",
    "rxjs": "5.0.1",
    "zone.js": "^0.7.4"
You also must point to systems that you main module is inside "app" directory:
index.html

    <script src="systemjs.config.js"></script>
    <script>
      System.import('/app').catch(function(err){ console.error(err); });
    </script>

Important: you must remove main.js reference from index.html
And run again:npm install and after :tsc -p .

If everything is OK you should refresh and see the app running as usual.

Little Experiment

Now lets try to import some file into main.ts file using import command:
main.ts


import './app'
declare var angular: ng.IAngularStatic;//must not override global angular
angular.bootstrap(document.body, ['myApp'], { strictDi: true });

Now you can remove app.js reference from index.html and see that app still running (since the code imported by systemjs!)

You can view full code on this branch

Step 05 - Install Angular Upgrade

Now we about to enter cherry-in-the-cake zone of this article - start using angular2 and angular1 in the same project

 npm i @angular/upgrade -D
This angular2 module makes you to be able to include angular2 modules into your angular1 project.
Lets add angular2 module named AppModule
app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { UpgradeModule } from '@angular/upgrade/static'
@NgModule({
  imports: [
    BrowserModule,
    UpgradeModule,
  ],
})
export class AppModule {
  ngDoBootstrap() {}
}

Now the only thing left is to inject your old myApp module angular2 way:
main.ts

/*angular.bootstrap(document.body, ['myApp'], {strictDi: true});*/
import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { UpgradeModule } from '@angular/upgrade/static';
import { AppModule } from './app.module';
platformBrowserDynamic().bootstrapModule(AppModule).then(platformRef => {
  const upgrade = platformRef.injector.get(UpgradeModule) as UpgradeModule;
  upgrade.bootstrap(document.body, ['myApp']);
});

Voula! you running angular2 and angular1 together now!
You can view source code on this branch

Thanks for reading

1/18/17

Unit Tests In Angular2 - part 3 (Component That Uses Service)

In previous post we've learned how to test the angular2 component.
That was very nice and we have a lot of fun, but everybody knows that in real life many components may use services to bring data from server.
Lets demonstrate it on our user component:
Lets make it to display friends list of this user:



@Component({
  selector: 'my-app',
  template: `<span>name: <strong>Victor Savkin</strong></span>
   <hr/>
   <strong>Friends:</strong>
   <ul>
     <li *ngFor="let friend of friends">
       {{friend}}
     </li>
   </ul>`
})
export class App {
   
    public friends:string[]=[]
    constructor(private usersService:UsersService) {
    }
    ngOnInit(): void {
       this.usersService.getUsers().subscribe(
         users => {
           this.friends=users;
         },
         error=>console.log(error) 
       );
    }
}


And the code of UsersSerivice:

import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class UsersService {
  constructor(private http:Http) { }
  
  getUsers(){
    return this.http.get('api/users.json')
      .map(response => response.json());
  }
}


So How To Test This Thing?

Lets say we want to test that request populates the "friends" section with friends names.
Since it is bad practice to make real http request for testing purposes - we need to create a mock of UsersService:


import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/of';
  
  class MockUsersService {
    public get() {return  Observable.of(['John', 'Steve']);}
  }

Once we have the mock of UsersService -lets inject it into the module instead of usersService:

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [UserComponent], 
      providers:[// <--HERE IS THE MAGIC!!!
       { provide: UsersService, useClass: MockUsersService}
      ],
      imports: [ HttpModule,BrowserModule ]
    })
    .compileComponents();
  }));

Great, inst it?
Now we can test the component and see if friends are displayed as planned:

  beforeEach(() => {
    fixture = TestBed.createComponent(UserComponent);
    comp = fixture.componentInstance;
    comp.user = new UserModel('Vasia','Kozlov')
    de = fixture.debugElement.query(By.css('span'));
    element = fixture.nativeElement;// to access DOM element
  });

  it('should have list of friends displayed inside UL',  async(() => {
    fixture.detectChanges();
    fixture.whenStable().then(() => { 
      expect(element.querySelector('li:first-child').innerText).toBe('John');
      expect(element.querySelector('li:last-child').innerText).toBe('Steve');
    })
  }));

you can see the full code on this plunker

1/10/17

Unit Tests In Angular2 - part 2 (The Component)

Testing The Component

In previous post we've learned how to test the model (Simple javascript object) and the Service in angular2. Now I think' we ready for next step:

How To Test The Component

Lets say we have a User Component which should display the full name of some user:
(user-component.ts):


import { Component,  Input} from '@angular/core';
import {UserModel} from './user-model'
@Component({
    selector: 'user-component',
    template:   `{{ user.fullname() }}`
})
export class UserComponent {
    @Input() user:UserModel;
}

This component contains @input annotation - which means the parameter from outside (named user) should be set

The Test

As in case of Service we should start with setup the module with testBed util:
(user-component.spec.ts):



import {UserComponent} from './user-component'
import {UserModel} from './user-model'
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { By }           from '@angular/platform-browser';
import { DebugElement } from '@angular/core';

describe('UserComponent tests', function () {
  let de: DebugElement;
  let comp: UserComponent;
  let fixture: ComponentFixture;

  beforeEach(async(() => {
    TestBed.configureTestingModule({
      declarations: [  UserComponent ]
    })
    .compileComponents();
  }));

  beforeEach(() => {
    fixture = TestBed.createComponent(UserComponent);
    comp = fixture.componentInstance;
    comp.user = new UserModel('Vasia','Kozlov')// <--here we passing the outer parameter
    de = fixture.debugElement.query(By.css('span'));
  });

  it('should create component', () => expect(comp).toBeDefined() );

  it('should have fullname of user displayed inside "span" tag', () => {
    fixture.detectChanges();
    const h1 = de.nativeElement;
    expect(h1.innerText).toMatch(/Vasia Kozlov/i,
      ' should state user Full Name');
  });
});

As you can see - the outer parameter passed using fixture.componentInstance helper
You can view the running code on the plunker

1/5/17

Unit Tests In Angular2 - part 1 (Get Started)

Get Started

Here is link to amazing tutorial for someone who wanted to learn from real angular developers...
Angular 2 has it's way for writing unit tests, it is pretty resembles the angular1. The same jasmine, only in typescript

Example of Testing Person Model

Lets start with models since they are usual javascript objects:
(person-model.ts):


export class PersonModel {

    constructor(
        public firstname: string = '',
        public lastname: string = ''
    ) {};

}

So here how the tests should look:
(person-model.spec.ts):

import {PersonModel} from './person-model';

describe('PersonModel', () => {

  it('should return the correct properties', () => {

      var person = new PersonModel();
      person.firstname = 'Shlomo';
      person.lastname = 'The King';

      expect(person.firstname).toBe('Shlomo');
      expect(person.lastname).toBe('The King');

  });

});

Nothing complicate here...

Testing Angular2 Service

Next step I want to show how to test some service.
Services are usually built for send http requests and bring data:


import {Injectable} from '@angular/core';
import {Http} from '@angular/http';
import 'rxjs/add/operator/map';

@Injectable()
export class UsersService {
  constructor(private http:Http) { }
  
  get(){
    return this.http.get('api/users.json')
      .map(response => response.json());
  }
}

The Users service has only one method - get
So, this is how the tests should look:
users.service.spec.ts

import {inject, TestBed, async} from '@angular/core/testing';
import {HttpModule} from '@angular/http';

import {UsersService} from './users.service'
describe('Service: UsersService', () => {
  let service;
  
  //setup
  beforeEach(() => TestBed.configureTestingModule({
    imports: [ HttpModule ],
    providers: [ UsersService ]
  }));
  
  beforeEach(inject([UsersService], s => {
    service = s;
  }));
  
  //specs
  it('should return available users (async)', async(() => {
    service.get().subscribe(x => { 
      expect(x).toContain('sasha');
      expect(x).toContain('vasia');
      expect(x).toContain('pasha');
      expect(x.length).toEqual(3);
    });
  }));
  

}) 

Note that I'm using TestBed utility to initiate ngModel and the service with injected Http.
here is working plunker

12/14/16

Creating Material Chips Input For Angular2

What Are Those Chips I'm Talking About

Here are some of many implementations that can be found across the web:
materializecss
angularjs material
Look at this gif that demonstrates chips behavior:

Angular2 Chips

Recently I looked on Angular Material2 repository that being developed quickly those days. I noticed that currently the chips ui is not developed yet, So i decided to try to do it myself and here i want to share some of my thoughts about this challenge of mine...

References Of Experts

During my research i was helped reading by those great articles of those 3 great guys: implementing-angular2-forms-beyond-basics
linkup-custom-control-to-ngcontrol-ngmodel
understanding-controlvalueaccessor

First Way

We may make some component that gets chips array as two way binding parameter from its parent
HTML:


   //in parent component:
   values:string[]=['lolo']
    ...
   <chips [chips]="values"></chips>

chipsComponent.ts:

import {Component, Input, Output, EventEmitter} from '@angular/core'
@Component({
  selector: 'chips',
  template: `
   <div *ngIf="values">
      <span *ngFor="let value of values" style="font-size:14px"
          class="label label-default" (click)="removeValue(tag)">
        {{value}} <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
      </span>
      <span> | </span>
      <span style="display:inline-block;">
        <input [(ngModel)]="labelToAdd" style="width: 50px; font-size: 14px;" class="custom"/>
        <em class="glyphicon glyphicon-plus" aria-hidden="true" (click)="addValue(valueToAdd)"></em>
      </span>
    </div>
  `
})
export class Chips { 
  @Input()
  get chips() {
    return this.values;
  }
  set chips(val) {
    this.values = val;
    this.labelsChange.emit(this.values);
  }

  @Output()
  labelsChange: EventEmitter = new EventEmitter();

  removeValue(value:string) {
    var index = this.values.indexOf(value, 0);
    if (index != undefined) {
      this.values.splice(index, 1);
      this.labelsChange.emit(this.values);
    }
  }

  addValue(value:string) {
    this.values.push(this.labelToAdd);
    this.labelsChange.emit(this.values);
    this.labelToAdd = '';
  }
}

see this code runs in plunker

Second Way (using Angular2 Forms)

My goal was to create a component/driective that will use ngModel directive to update the model:



 <material-chips [(ngModel)]="tags" ></material-chips>


For this we need to implement valueAccessor interface:

import {Component, NgModel, NgModule, OnInit, Input, Output, EventEmitter, ElementRef, forwardRef} from '@angular/core'

import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';


const noop = () => {
};

export const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
    provide: NG_VALUE_ACCESSOR,
    useExisting: forwardRef(() => Chips),
    multi: true
};

@Component({
  selector: 'chips',
  template: `
    <div *ngIf="values">
      <span *ngFor="let value of values" style="font-size:14px"
          class="label label-default" (click)="removeValue(tag)">
        {{value}} <span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
      </span>
      <span> | </span>
      <span style="display:inline-block;">
        <input [(ngModel)]="labelToAdd" style="width: 50px; font-size: 14px;" class="custom"/>
        <em class="glyphicon glyphicon-plus" aria-hidden="true" (click)="addValue(valueToAdd)"></em>
      </span>
    </div>
  `,
   providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR] 
})
export class Chips  implements ControlValueAccessor { 
  //by the Control Value Accessor
  private onTouchedCallback: () => void = noop;
  private onChangeCallback: (_: any) => void = noop;
  registerOnChange(fn: any) { this.onChangeCallback = fn;}
  registerOnTouched(fn: any) { this.onTouchedCallback = fn;}

  @Output()
  labelsChange: EventEmitter = new EventEmitter();

  removeValue(value:string) {
    var index = this.values.indexOf(value, 0);
    if (index != undefined) {
      this.values.splice(index, 1);
      this.labelsChange.emit(this.values);
    }
  }

  addValue(value:string) {
    if(!this.labelToAdd || this.labelToAdd.trim()===''){return;}
    this.values.push(this.labelToAdd);
    this.labelsChange.emit(this.values);
    this.labelToAdd = '';
  }
  
  //From ControlValueAccessor interface
  writeValue(value: any) {
      if (value !== this.values) {
          this.values = value;
      }
  } 

}


7/21/16

Building A Short-Description Pipe Angular 2

Pipe is same thing that filter in angluar1. Lets take a look on code that checks if field has too much characters and if it has - replaces the extra characters with ... :


import { Pipe } from '@angular/core';

@Pipe({
  name: 'short_description'
})
export class ShortDescriptionPipe {
  transform(value) {
    let transformedValue;
    if (value && value.length > 100) {
      transformedValue = `${value.substring(0, 100)}...`;
    } else {
      transformedValue = value;
    }

    return transformedValue;
  }


Now if we have some field contain more than 100 characters it will display only first 100 characters

    <div>
      <h2>Hello {{name | short_description }}</h2>      
    </div>

Extending The Pipe To Get "Maximum Chars" Param

In previous code the characters length is statically restricted to 100 chars. But what if we wish to dynamicaaly pass the maximum chars number?


    <div>
      <h2>Hello {{name | short_description : 4}}</h2>      
    </div>
As in angular1 the pipe params prefixed with ::

import { Pipe } from '@angular/core';

@Pipe({
  name: 'short_description'
})
export class ShortDescriptionPipe {
  transform(value, args?) {//args contains param
    if(!args ){
      args= 100;
    }
    let transformedValue;
    if (value && value.length > args) {
      transformedValue = `${value.substring(0, args)}...`;
    } else {
      transformedValue = value;
    }

    return transformedValue;
  }


7/11/16

3 Different Ways To Use ngFor

Introduction

Like ng-repeat directive of angular 1. there is ngFor directive in angular2. it uses for display lists of items.
For example sake - lets take situation we need to display table of site users.
In old angular1 the template should look like this:
angular1 template


    <div>
      <h2>{{name}}</h2>
      <div  ng-if="userList.length===0">No Users Yet</div>
      <table ng-if="userList.length" >
        <tr><th>First Name</th><th>Last Name</th></tr>
        <!-- Look here -->
        <tr ng-repeat="user in userList">
         <td>
           {{user.firstName}}
         </td>
         <td>
           {{user.lastName}}
         </td>         
        </tr>
      </table>
    </div>

And here is controller & service code:
angular1 code

   //service 
   app.factory('usersSrv', function($http, $q) {
     function get(){
       var defer = $q.defer();
       $http.get('./users.json').success(function(data){
         defer.resolve(data)
       });
       return defer.promise;
     }
  
     var service = { 
        getUsers: get
     }

     return service;
   });
    //controller:
   $scope.userList = [];
   usersSrv.getUsers().then(function(users){
    $scope.userList = users; 
   })

Code: plunkr


The same scenario could be written in angular2 like this
template of app.component.ts

      <table *ngIf="userList.length">
        <tr>
            <th>First Name</th>
            <th>Last Name</th>
        </tr>
        <!-- Look here -->
        <tr *ngFor="let user of userList">
         <td>
           {{user.firstName}}
         </td>
         <td>
           {{user.lastName}}
         </td>         
        </tr>
      </table>

If there are some users in our db - they will be shown in table.
Currently the data taken from static array:

export class App {
  public userList:Array=[];
  constructor(userService:UserService) {
    this.name = 'Users Table:'
    this.userList =  [{firstName:'Vasia', lastName:'kozlov'}]
  }
}

we can see users table and everything is fine.

Code: plunk

Promise

The things starting to be more complicate when users collection is loaded from http request. It is complicate because users data now is asyncronous.
So, the first way to handle this thing is to use good old Prmoise known to us well from angular1.
Unlike angular1 we need to import toPromise operator of rxjs library.
users.servise.ts:


import { Injectable }    from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/add/operator/toPromise';//import of "topromise" method from rxjs lib

@Injectable()
export class UserService {
  private url:string = './users.json';
  constructor(private http: Http) {}
  getUsers(): Promise {//method must return promise
    return this.http.get(this.url)
    .toPromise()
    .then(response => response.json());
  }
}

Now in the component code we able to use the "then" method for getting the callback of asyncronous method.
app.component.ts:

import {Component} from '@angular/core';
import {UserService} from './user.servise';
@Component({
  selector: 'my-app',
  providers: [],
  template: `
      ...
      ...
      ...
  `,
  providers: [UserService]
})
export class App {
  public userList:Array=[];
  constructor(userService:UserService) {
    this.name = 'Users Table:'
    userService.getUsers().then(//Here we can use "then"
      users => this.userList=users,
      error => console.log(error)
    );
  }
}

The good side here (for me) is that it very similar to angular1 way.
Code: plunk

Subscribe

The second attitude is to use map method of rxjs library.
users.servise.ts:


import { Injectable }    from '@angular/core';
import { Headers, Http } from '@angular/http';
import 'rxjs/Rx';

@Injectable()
export class UserService {
  private url:string = './users.json';
  constructor(private http: Http) {}
  getUsers() {
    return this.http.get(this.url).map(response => response.json());
  }
}

This map method returns Rx.Observable object, thus in component code we will need to use subscribe for handle the async data:
app.component.ts:

import {Component} from '@angular/core';
import {UserService} from './user.servise';
@Component({
      ...
      ...
      ...
  providers: [UserService]
})

export class App {
  public userList:Array=[];
  constructor(userService:UserService) {
    this.name = 'Users Table:';
    userService.getUsers().subscribe(
      users => this.userList=users,
      error=>console.log(error)
    );
  }
}

I like this way because it looks more shorter (no need to use conversion to promise like in previous way).
Code: plunk

Using Async Pipe

Unlike in angular1 there is a way in angular2 to pass observable collection directly to ngFor directive.
We can do this using angular2 async pipe.
template of app.component.ts


    <div>
      <h2>{{name}}</h2>
      <div  *ngIf="userList.length===0">No Users Yet</div>
      <table >
        <tr><th>First Name</th><th>Last Name</th></tr>
        <!-- Look here -->
        <tr *ngFor="let user of userList | async">
         <td>
           {{user.firstName}}
         </td>
         <td>
           {{user.lastName}}
         </td>         
        </tr>
      </table>
    </div>

Usinp async pipe makes the component code even more shorter: app.component.ts:

import {Component} from '@angular/core';
import {UserService} from './user.servise';
@Component({
      ...
      ...
      ...
  providers: [UserService]
})

export class App {
  public userList:Array=[];
  constructor(userService:UserService) {
    this.name = 'Users Table:';
    //no subscribe needed
    this.userList=userService.getUsers();
  }
}

Little More About Async Pipe

Another cool thing about this pipe is - that it can be used not only in ngFor
For example - if you need to show "No Users Yet" message when no users found in DB, you may use async pipe too:
template of app.component.ts


    <div>
      <h2>{{name}}</h2>
      
      <!-- HERE -->
      <div  *ngIf="(userList | async)?.length===0">No Users Yet</div>
      <table *ngIf="(userList | async)?.length>0">
        <tr><th>First Name</th><th>Last Name</th></tr>
        <tr *ngFor="let user of userList | async">
         <td>
           {{user.firstName}}
         </td>
         <td>
           {{user.lastName}}
         </td>         
        </tr>
      </table>
    </div>


Code: plunk

Hope you have fun reading...

6/15/16

Form Validation In Angular2

Hi, My today's challenge is to create simple login form, like you can see in almost every web application.
Well, we will use plunker project already created for previous post since it has view called "login". Lets also add css styles of bootstrap library to the project for take advantage of this awesome framework with its form and validtaion styles.

Step 1 - ngModel

Yes, the famous two way data binding is still here. Only now it is using "[(" syntax:


   <form (ngSubmit)="login()">
      <div class="form-group">
        <label for="email">Email</label>
        <input type="text" class="form-control"
          [(ngModel)]="email"
            >
      </div>
      <div class="form-group">
        <label for="password">Password</label>
        <input type="password" class="form-control"
          [(ngModel)]="password"
           >
      </div>

      <button type="submit" class="btn btn-default">Submit</button>
  </form>

lets put simple code of component which only checks the input value is bound correctly:

export class Login {
  public  email: string;
  public  password: string;
  constructor(public router: Router){}
  login(){
    if(this.email && this.password){
       alert(this.email+' '+this.password)
    }
  }
}

Now when some characters filled into both inputs you can see it in alert after clicking submit.

Step 2 - ngForm

It is good practice to use "ngForm" directive which holds the status of form and its controls: The status can be valid (or "invalid"),pristine(or dirty) and touched
By using reference (attribute decorated with "#") and "hidden" directive i can show validation error labels.


 <div class="container">
   
   <form (ngSubmit)="login()">
      <div class="form-group">
        <label for="email">Email</label>
        <input type="text" class="form-control"  required
          [(ngModel)]="email"   ngControl="emailctrl" #emailctrl="ngForm"
            >
        <div [hidden]="emailctrl.valid || emailctrl.pristine" class="alert alert-danger">
          Email is required
        </div>
      </div>
      <div class="form-group">
        <label for="password">Password</label>
        <input type="password" class="form-control"  required
          [(ngModel)]="password"  ngControl="passctrl" #passctrl="ngForm"
           >
        <div [hidden]="passctrl.valid || passctrl.pristine" class="alert alert-danger">
          Passwd is required
        </div>           
      </div>

      <button type="submit" class="btn btn-default">Submit</button>
  </form>
  </div>

From now - if you typing something in one of the controls and then deleting it - the validation messages displayed.

Here is running code: Hope you have fun reading...

6/10/16

Creating Preloader In Angular2 app

Current Challenge

Many sites and webapps have some cool animation that plays before all the site resources (like css, scripts and other stuff) fully loaded.
You see this cool animation (or progress bar) playing for some time and then all the site elements appear.(Instead of staring in some blank page)
In this post i decided to find out how to create such animation in my angular2 experimental site.

Preloader animations

First of all - for making some animation you must create a proper CSS code. Since i have no time and talent to make this CSS by myself, i made a shortcut and used this cool css preloaders site for taking CSS of one of its awesome animations.


.spinner {
  width: 40px;
  height: 40px;
  background-color: #333;

  margin: 100px auto;
  -webkit-animation: sk-rotateplane 1.2s infinite ease-in-out;
  animation: sk-rotateplane 1.2s infinite ease-in-out;
}

@-webkit-keyframes sk-rotateplane {
  0% { -webkit-transform: perspective(120px) }
  50% { -webkit-transform: perspective(120px) rotateY(180deg) }
  100% { -webkit-transform: perspective(120px) rotateY(180deg)  rotateX(180deg) }
}

@keyframes sk-rotateplane {
  0% { 
    transform: perspective(120px) rotateX(0deg) rotateY(0deg);
    -webkit-transform: perspective(120px) rotateX(0deg) rotateY(0deg) 
  } 50% { 
    transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg);
    -webkit-transform: perspective(120px) rotateX(-180.1deg) rotateY(0deg) 
  } 100% { 
    transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
    -webkit-transform: perspective(120px) rotateX(-180deg) rotateY(-179.9deg);
  }
}

HTML element

To make this animation to work we need to put its "spinner" class on some html element that will appear on the view before main application component loaded and will disappear immediately afterwise.
To achieve this effect we can put this element inside the main component tag, so after its contents will load - the inner element will be simply overriden


    <my-app>
      <div class="spinner"></div>
    </my-app>

Thats it - we achieved our goal without writing even single angular2 line! It little bit disappointing but it also good practice to do things as simple as possible

Here is running code: Hope you have fun reading...

5/25/16

Routes In Angular2 (Part 2)

In previous post we talked about routes in angular2. We saw some basic example of app using routes. But what about nested routes?

Nested Routes

Lets say for example that we need in our application to have a login page which has no menus on it. After passing authentication user should be redirected to protected pages which have the same menus on each of them:

Step 1

Transfer application to use nested routes is very easy.
First you need to create the middle ware route which will host its own routes directive on it. Lets call it layout.
On this middle ware view we will locate the menu.

import {Component} from 'angular2/core'
import {RouteConfig, Router, Route,  ROUTER_DIRECTIVES} from 'angular2/router';
...
@Component({
  selector: 'layout',
 template: `
    <h2>Hello {{name}}</h2>
    <!-- menu is located here now -->
    <a [routerLink]="['Layout']">Dashboard</a> | 
    <a [routerLink]="['Reports']">Reports</a> |
    <a [routerLink]="['Login']">Login</a>
    <hr>
   <!-- router directive -->
   <router-outlet></router-outlet>, 
 directives: [ROUTER_DIRECTIVES]
})

  
@RouteConfig([
   new Route({path: '/', name: 'Dashboard', component: Dashboard, useAsDefault:true}),
   new Route({path: '/reports', name: 'Reports', component: Reports})
])
export class Layout {
  constructor(){
    this.name = 'Angular2 Nested Routes';
  }
}

Step 2

Next thing lets create the login page which will located at the base root route "/login".

import {Component} from 'angular2/core'

@Component({
  selector: 'login',
 template: `
   <div>
     <h1>Please Log In</h1>
     <div style="text-align:center">
           username:<input> 
     </div>
     <div style="text-align:center">
           password:<input> 
     </div>
     <div style="text-align:center">
      <button (click)="login()">login</button>
    </div>
   </div>  `
})

export class Login {
  constructor(public router: Router){}
  login(){
    this.router.navigate(['Layout']);
  }
}


Also lets create the Dashboard page which will located at the inner route "layout/dashboard".

Step 3

Last thing we should modify the root "app" component so it will support nested routes:

import {Component} from 'angular2/core'
import {RouteConfig, Router, Route,  ROUTER_DIRECTIVES} from 'angular2/router';
import {Layout} from './layout';
import {Login} from './login';


@Component({
  selector: 'my-app',
  template: `
      <router-outlet></router-outlet>
  `,
  directives: [ROUTER_DIRECTIVES]
})
@RouteConfig([
   new Route({path: '/layout/...', name: 'Layout', component: Layout}),
   new Route({path: '/login', name: 'Login', component: Login}),
   {
    path: '/**',
    redirectTo: ['Layout']
  }
])
export class App {
}

Here is running code: Hope you have fun reading...

5/11/16

Routes In Angular2 (Part 1)

What are Routes?

Routes are way to access various parts of website using friendly urls. For example if you have a motorcycle store - it will be very convenient if you can navigate to details of page of awesome suzuki GSX1000 using url like:
mybikestore.com/suzuki/GSX1000

(instead of using things like:
mybikestore.com?product=%20%dfgg;ereGSX1000%dfg
which you have no chance to remember)
This way the url pretty clear for users and makes much more sense for developers too.
cannot stop myself from putting here picture of GSX1000 2016

Routes in Angular2

Since when talking about angularjs2 we talking about single page application architecture there all the work done by javascript. The routes in angular (both 1. and 2) is the way to load different views (like different pages) of the website. The changes in url triggering javascript event and javascript responds by loading corresponding views, pretty cool isnt it?

Server

Speaking about single page application - the idea of single page app is that only one page should be served from the server - so it need to be specially configured.
Here is configuration of nodejs express server which makes it to serve only index page no matter of what route was chosen.

var express = require('express');
var app = express();
app.use(express.static(__dirname));

app.get('/*', function(req, res){
    res.sendFile(__dirname + '/index.html');
});
app.listen(process.env.PORT || 3000, function () {
  console.log('Example app listening on port 3000!');
});



Routes in angular2

To implement routes in angular2 'angular2/router' module must be included


import {ROUTER_PROVIDERS, APP_BASE_HREF} from 'angular2/router';

Also, in the code of main component must present route definitions part - a code which defines the routes and their urls:

@Routes([
  {
    path: '/',
    component: DashboardComponent
  },
  {
    path: '/reports',
    component: ReportsComponent
  }
])

Notice that in this example we have two views: "Dashboard" and "Reports"

View

Like in angular1 - if you want to load routed views in your application you must use the ROUTER DIRECTIVE in the view of the component


import {Component} from 'angular2/core';
import {ROUTER_DIRECTIVES, Router, Route, RouteConfig} from 'angular2/router';
...

@Component({
  selector: 'app',
  template: `
    ...
    <router-outlet></router-outlet>
  `,
  directives: [ROUTER_DIRECTIVES]
})

Here is running code: Hope you have fun reading...

Getting started with docker

It is very simple to get started usig docker. All you need to do-is download the docker desktop for your system Once you get docker syste...