First Introductions Angular2 use Service, Http, Components and Routing.

download11

Hi my name is Pascal Brewing and i want to show you how to use angular2. First we need a functional Es6 to Es5 compiling Setup. For this Tutorial you need Node, Traceur, Gulp, Git and ruby sass. Actually i used angular2 alpha27, please notice angular2 is not production ready!


App Bootstrap part

If you are using angular before then you will know you can bootstrap your app , cann because ng-app=”app” do this job for you this is changed in angular2 you have to Bootstrap your app manual.
Look at ‘client/app/app.ts’ on the end you will see a bootstrapping part this will load your app the deviceready is usefull if you wanna use Cordova.

this.bindEvents = function () {
     document.addEventListener('deviceready', function () {
     bootstrap(App);
  }, false);
    };
  //If cordova is present, wait for it to initialize, otherwise just try to
  //bootstrap the application.
  if (window.cordova !== undefined) {
    this.bindEvents();
  } else {
    console.log('no device');
    bootstrap(App);
  }

App Routing

About angular2 alpha 24 we have a router thats great and we can use more then on component its look like a little bit simular like the ui state router from angular1, before we can use it we have to import it
check this line of code

/// <reference path="../typings/tsd.d.ts" />
  import {Component, View, bootstrap, NgFor} from 'angular2/angular2';
  import {RouteConfig, RouterOutlet, RouterLink, routerInjectables} from 'angular2/router';

Now you can configure some routes with your availables Components

@RouteConfig([
  {path: '/', component: Todo, as: 'todo'},
  {path: '/about', component: About, as: 'about'}
  ])

dont forget to import your Components in your app.ts

import {Todo} from './components/todo/todo';
  import {About} from './components/about/about';

ok but this is nout enough you have to explicit inject it in your view like this:

@View({
  directives: [RouterOutlet, RouterLink]
  })

ok you have inject it know we wann use a partial to use it what you need is a template with a <router-outlet></router-outlet>

@View({
  template: `
      <div class="view">
         <div class="bar bar-header">
            <div class="bar bar-header">
                <div class="button-bar">
                    <a class="button" router-link="todo">Todo - List</a>
                    <a class="button" router-link="about">About</a>
                 </div>
               </div>
            </div>
         <div class="content padding has-header">
      <router-outlet></router-outlet>
    </div>
  </div>
  `,
  directives: [RouterOutlet, RouterLink]
  })

linking is very easy with a simple <a class=”button” router-link=”todo”>Todo – List</a> todo is the name what you give in your route config as ‘as’.
Add to the bootstrap part the routerInjectables Remember:

  bootstrap(App, [routerInjectables]);

your app.ts now will look like this

/// <reference path="../typings/tsd.d.ts" />
  import {Component, View, bootstrap, NgFor} from 'angular2/angular2';
  import {RouteConfig, RouterOutlet, RouterLink, routerInjectables} from 'angular2/router';

  import {Todo} from './components/todo/todo';
  import {About} from './components/about/about';
  @Component({
    selector: 'app'
  })
  @RouteConfig([
    {path: '/', component: Todo, as: 'todo'},
    {path: '/about', component: About, as: 'about'}
  ])
  @View({
    template: `
    <div class="view">
         <div class="bar bar-header">
             <div class="bar bar-header">
                 <div class="button-bar">
                       <a class="button" router-link="todo">Todo - List</a>
                       <a class="button" router-link="about">About</a>
                     </div>
                  </div>
               </div>
            <div class="content padding has-header">
           <router-outlet></router-outlet>
         </div>
       </div>
  `,
  directives: [RouterOutlet, RouterLink]
  })
  class App {}
   this.bindEvents = function () {
     document.addEventListener('deviceready', function () {
       bootstrap(App, [routerInjectables]);
  }, false);
  };
  //If cordova is present, wait for it to initialize, otherwise just try to
  //bootstrap the application.
  if (window.cordova !== undefined) {
    this.bindEvents();
  } else {
    console.log('no device');
    bootstrap(App, [routerInjectables]);
  }

Now we can route and use some Components in our app ok but how ?

App Components

Ok let´s started to add a Component name Todo
for a simple Component we need a import like this

import {Component, View} from 'angular2/angular2';

ok then we need a @Component part and a @View part

import {Component, View} from 'angular2/angular2';
  @Component({
    selector: 'component-1'
  })
  @View({
    template: `
      <div>Hello iam the Todo Component</div>
  `
  })
  export class Todo {
    constructor() {}
  }

now you will see a simple Hello World example on a route with a component.
So you can use som view directives like NgFor, NgIf etc. have a look at this two directives.

First add your import the directives with

import {Component, View, NgFor, NgIf} from 'angular2/angular2';

ok bind it to your View

@View({
  template: `
    <div>Hello iam the Todo Component</div> `,
  directives: [NgFor, NgIf]
  })

ok lets use it on your div the NgIf

import {Component, View, NgFor, NgIf} from 'angular2/angular2';

  @Component({
    selector: 'component-1'
  })
  @View({
    template: `
      <div *ng-if="ifBool">Hello iam the Todo Component</div>
  `,
  directives: [NgFor, NgIf]
  })
  export class Todo {
    ifBool: boolean;

  constructor() {
    this.ifBool = true;
    }
  }

the args on your div *ng-if=”ifBool” check if the bool is true or false. To toggle it, add a button on your view and a toggle method to your Component

import {Component, View, NgFor, NgIf} from 'angular2/angular2';

  @Component({
    selector: 'component-1'
  })
  @View({
    template: `
     <div *ng-if="ifBool">Hello iam the Todo Component</div>
     <button (click)="toggleBoolean($event)">toggle me</button>
  `,
  directives: [NgFor, NgIf]
  })
  export class Todo {
    ifBool: boolean;

  constructor() {
    this.ifBool = true;
  }
  toggleBoolean(e){
    e.preventDefault();
    this.ifBool = !this.ifBool;
    }
  }

hit the button and you will see the text is toggled.
Now let us use the NgFor Directive, for this we need some Data:

import {Component, View, NgFor, NgIf} from 'angular2/angular2';

  @Component({
    selector: 'component-1'
  })
  @View({
    template: `
      <div class="list">
        <div *ng-for="#item of list" class="item">
        {{item.title}}
      </div>
    <div class="item" *ng-if="ifBool">Hello iam the Todo Component</div>
   <button class="button" (click)="toggleBoolean($event)">toggle me</button>
 </div>

  `,
  directives: [NgFor, NgIf]
  })
  export class Todo {
    ifBool: boolean;
    list: Array<Object>;
  constructor() {
    this.ifBool = true;
    this.list = [
  {
  "_id": "4ad2b0e4d8fb7f550cc1d962",
  "completed": false,
  "title": "Lorem Ipsum",
  "public": true,
  "order": 2
  },
  {
  "_id": "4ad2b0e4bafd7f5532c2d962",
  "completed": false,
  "title": "Lorem Ipsum",
  "public": true,
  "order": 3
      }
    ];
  }
  toggleBoolean(e){
    e.preventDefault();
    this.ifBool = !this.ifBool;
    }
  }

the result is a list of titles. Ok let us check something about the ng-if and th ng-for to bind it on the same Dom Element.

template: `
  <div class="list">
     <div *ng-if="ifBool" *ng-for="#item of list" class="item">
       {{item.title}}
     </div>
       <button class="button" (click)="toggleBoolean($event)">toggle me</button>
  </div>
  `

ok what happens here we don´t see anything but why? Check your console for that you will see something like this

Only one template directive per element is allowed: ng-if ifBool and ng-for cannot be used simultaneously in null

  Error
  at new BaseException (http://localhost:5555/lib/angular2.js?v=0.0.0:4188:25)
  at http://localhost:5555/lib/angular2.js?v=0.0.0:12122:25
  at Map.forEach (native)
  at Function.execute.MapWrapper.forEach 
     (http://localhost:5555/lib/angular2.js?v=0.0.0:4534:15)
  at ViewSplitter.execute.ViewSplitter.process 
     (http://localhost:5555/lib/angular2.js?v=0.0.0:12118:24)
  at CompileControl.execute.CompileControl.internalProcess 
     (http://localhost:5555/lib/angular2.js?v=0.0.0:11382:20)
  at CompilePipeline.execute.CompilePipeline._process 
     (http://localhost:5555/lib/angular2.js?v=0.0.0:19306:52)
  at CompilePipeline.execute.CompilePipeline._process 
     (http://localhost:5555/lib/angular2.js?v=0.0.0:19316:24)
  at CompilePipeline.execute.CompilePipeline._process 
     (http://localhost:5555/lib/angular2.js?v=0.0.0:19316:24)
  at CompilePipeline.execute.CompilePipeline.process 
     (http://localhost:5555/lib/angular2.js?v=0.0.0:19301:18)

the important part is “Only one template directive per element is allowed: ng-if ifBool and ng-for cannot be used simultaneously in null” that means you cant use two directives on the same Element this is changed from angular1 to angular2 more information about this you can get here

App Services

So let use some Data from a Service. Ok we need a new file create a folder name it services and add a TodoList.ts in there. Ok we don´t need angular here we create a simple class like this

export class TodoList{
   collection: Array<Object>;
     constructor(){
      this.collection = [
  {
  "_id": "4ad2b0e4d8fb7f550cc1d962",
  "completed": false,
  "title": "Lorem Ipsum",
  "public": true,
  "order": 2
  },
  {
  "_id": "4ad2b0e4bafd7f5532c2d962",
  "completed": false,
  "title": "Lorem Ipsum",
  "public": true,
  "order": 3
      }
    ];
  }
  get(){
     return this.collection;
    }
  }

To use our TodoList service we have to go in our Todo component.
import the service

import {TodoList} from '../../services/TodoList';

inject the service

@Component({
     selector: 'component-1',
     appInjector: [TodosList]
  })

use the service

export class Todo {
     ifBool: boolean;
     service:TodoList;

  constructor(service:TodoList) {
     this.service = service;
     this.getList();
  }
  getList(){
     let self = this;
     let promise = new Promise(resolve => {
  resolve(this.service.get());
  });
  promise.then(function (collection) {
     self.list = collection;
      });
    }
  }

full example of your Service :

export class TodoList{
      collection: Array<Object>;
 constructor(){
   this.collection = [
  {
  "_id": "4ad2b0e4d8fb7f550cc1d962",
  "completed": false,
  "title": "Lorem Ipsum",
  "public": true,
  "order": 2
  },
  {
  "_id": "4ad2b0e4bafd7f5532c2d962",
  "completed": false,
  "title": "Lorem Ipsum",
  "public": true,
  "order": 3
      }
    ];
  }
  get(){
    return this.collection;
    }
  }

full example of your Component

import {Component, View, NgFor, NgIf} from 'angular2/angular2';
  import {TodoList} from '../../services/TodoList';

  @Component({
     selector: 'component-1',
     appInjector: [TodoList]
  })
  @View({
     template: `
     <div class="list">
       <div *ng-for="#item of list" class="item">
         {{item.title}}
       </div>
     </div>
  `,
  directives: [NgFor, NgIf]
  })
  export class Todo {
    ifBool: boolean;
    list: Array<Object>;
    service:TodoList;

  constructor(service:TodoList) {
     this.service = service;
     this.getList();
  }
  getList(){
     this.list = this.service.get();
    }
  }

still works, ok but this is not a real example ok let us use some Http Calls.

App Http

For a Http request we have to inject at first the httpInjectables in our app.ts bootstrap part

bootstrap(App, [routerInjectables, httpInjectables]);

then we have to add some imports in our Service to use the http we using here the Inject in our service contructor

constructor(@Inject(HttpFactory) http:Http) {

Ok and then we add a fetch method to our Service to send the call

import {Inject} from 'angular2/di';
  import {httpInjectables, Http} from 'angular2/http';
  import {HttpFactory} from 'angular2/src/http/http';
  import {IHttp} from 'angular2/src/http/interfaces';

  export class CinemaList {
  API_KEY: string = '7waqfqbprs7pajbz28mqf6vz';
  API_URL: string =  'http://api.rottentomatoes.com/api/public/v1.0/lists/movies/in_theaters.json';
  pageSize: number = 50;
  params: string
  requestUrl: string;
  http: any;
  data: Array<Object>;
  constructor(@Inject(HttpFactory) http:Http) {
     this.http = http;
     this.params = `?apikey=${this.API_KEY}&page_limit=${this.pageSize}`;
     this.requestUrl = this.API_URL + this.params;
  }
  fetch() {
     let self = this;
     return this.http(this.requestUrl);
    }
  }

To get the data into our Component we have to modify the getList method:

getList(){
      this.service.fetch().subscribe(function (res) {
        debugger;
     });
   }

you fetch a response Object into your component see the full usage example:

import {Component, View, NgFor, NgIf} from 'angular2/angular2';
  import {CinemaList} from '../../services/CinemaList';

  @Component({
     selector: 'component-1',
     appInjector: [CinemaList]
  })
  @View({
     template: `
       <div class="list card" *ng-for="#movie of movies" [id]="movie.id">
       <div class="item item-avatar">
             <img [src]="movie.posters.thumbnail">
          <h2>{{movie.title}}</h2>
         <p>{{movie.release_dates.theater}} {{movie.year}}</p>
       </div>

  <div class="item item-body">
     <img class="full-image" [src]="movie.posters.detailed">
     <p>
        {{movie.synopsis}}
  </p>
  <p>
     <a href="#" class="subdued">1 Like</a>
     <a href="#" class="subdued">5 Comments</a>
    </p>
  </div>

  <div class="item tabs tabs-secondary tabs-icon-left">
    <a class="tab-item" href="#">
     <i class="icon ion-thumbsup"></i>
       Like
  </a>
  <a class="tab-item" href="#">
     <i class="icon ion-chatbox"></i>
       Comment
  </a>
  <a class="tab-item" href="#">
     <i class="icon ion-share"></i>
       Share
      </a>
    </div>
  </div>
  `,
  directives: [NgFor, NgIf]
  })
  export class Todo {
    list:CinemaList;
    movies:Array<Object> = [];
    data: Array<Object>;
  constructor(list:CinemaList) {
     this.list = list;
     this.getList();
  }
  getList(){
    let self = this;
    this.list.fetch().subscribe(function (res) {
      self.data = JSON.parse(res._body);
      self.movies = self.data.movies;
     });
    }
  }

App Code

The Tutorial code example is available here

    git clone git@github.com:DrMabuse23/relution-live-data-ng2.git

To run it in your Browser cd into the client directory and do following commands npm i will donwloading all needed packages from npm and gulp serve.dev open the page on http://localhost:5555.

cd client
  npm i
  gulp serve.dev

run on your device

cd client
  cordova platform add ios
  cordova build ios
  cordova run ios

Thx for reading …