Angular 2 News tutorial in Visual Studio Code part 1

This tutorial takes us through the steps of creating an Angular application in TypeScript using some cool libraries and APIs. We will implement a news application based on data from New York Times API. We will use Reactive extensions Rx.js for the http calls, lodash for array manipulation and ng-2 bootstrap  for angular 2 bootstrap directives ,like image carousel and pagination.

We start creating a basic Angular 2 app following Angular 2 Quickstart (version is RC 2). We have to modify some steps and add some lines of code.After creating the project folder we have to add 4 files : package.json , tsconfig.json ,typings.json and systemjs.config.js. There are some slight differences so please copy the code from the tabs below :

package.json


{
 "name": "angular2-quickstart",
 "version": "1.0.0",
 "scripts": {
 "start": "tsc && concurrently \"npm run tsc:w\" \"npm run lite\" ",
 "lite": "lite-server",
 "postinstall": "typings install",
 "tsc": "tsc",
 "tsc:w": "tsc -w",
 "typings": "typings"
 },
 "license": "ISC",
 "dependencies": {
 "@angular/common": "2.0.0-rc.2",
 "@angular/compiler": "2.0.0-rc.2",
 "@angular/core": "2.0.0-rc.2",
 "@angular/http": "2.0.0-rc.2",
 "@angular/platform-browser": "2.0.0-rc.2",
 "@angular/platform-browser-dynamic": "2.0.0-rc.2",
 "@angular/router": "2.0.0-rc.2",
 "@angular/router-deprecated": "2.0.0-rc.2",
 "@angular/upgrade": "2.0.0-rc.2",
 "systemjs": "0.19.27",
 "core-js": "^2.4.0",
 "reflect-metadata": "^0.1.3",
 "rxjs": "5.0.0-beta.6",
 "zone.js": "^0.6.12",
 "angular2-in-memory-web-api": "0.0.12",
 "bootstrap": "^3.3.6",
 "lodash": "^4.13.1",
 "ng2-bootstrap": "^1.0.17"
 },
 "devDependencies": {
 "concurrently": "^2.0.0",
 "lite-server": "^2.2.0",
 "typescript": "^1.8.10",
 "typings":"^1.0.4"
 }
}


tsconfig.json


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

typings.json


{
  "globalDependencies": {
    "core-js": "registry:dt/core-js#0.0.0+20160317120654",
    "jasmine": "registry:dt/jasmine#2.2.0+20160505161446",
    "node": "registry:dt/node#6.0.0+20160613154055"
  },
   "dependencies": {
    "lodash": "registry:npm/lodash#4.0.0+20160416211519"
  }
}


systemjs.config.js


/**
 * System configuration for Angular 2 samples
 * Adjust as necessary for your application needs.
 */
(function(global) {
  // map tells the System loader where to look for things
  var map = {
    'app':                        'app', // 'dist',
    '@angular':                   'node_modules/@angular',
    'angular2-in-memory-web-api': 'node_modules/angular2-in-memory-web-api',
    'rxjs':                       'node_modules/rxjs',
    'moment':                     'node_modules/moment/moment.js',
    'lodash':                      'node_modules/lodash/lodash.js'
    
  };
  // packages tells the System loader how to load when no filename and/or no extension
  var packages = {
    'app':                        { main: 'main.js',  defaultExtension: 'js' },
    'rxjs':                       { defaultExtension: 'js' },
    'angular2-in-memory-web-api': { main: 'index.js', defaultExtension: 'js' },
    'lodash':                     { defaultExtension:'js'}

    
  };
  var ngPackageNames = [
    'common',
    'compiler',
    'core',
    'http',
    'platform-browser',
    'platform-browser-dynamic',
    'router',
    'router-deprecated',
    'upgrade',
  ];
  // Individual files (~300 requests):
  function packIndex(pkgName) {
    packages['@angular/'+pkgName] = { main: 'index.js', defaultExtension: 'js' };
  }
  // Bundled (~40 requests):
  function packUmd(pkgName) {
    packages['@angular/'+pkgName] = { main: pkgName + '.umd.js', defaultExtension: 'js' };
  };
  // Most environments should use UMD; some (Karma) need the individual index files
  var setPackageConfig = System.packageWithIndex ? packIndex : packUmd;
  // Add package entries for angular packages
  ngPackageNames.forEach(setPackageConfig);
  var config = {
    map: map,
    packages: packages
   
  }
  System.config(config);
})(this);



We install the packages listed in packages.json using npm

npm install

npm run typings install

Then we create an app folder and inside this we create 2 subfolders : movies and world. In these 2 subfolders lets create a simple component for each one : MoviesComponent in movies and WorldNewsComponent in world. Components are the basic building blocks of Angular applications. A component controls a portion of the screen — a view — through its associated template.

movies.component.ts


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


@Component({
    template: '<h1>Movies Component</h1>'
})

export class MoviesComponent {

}

worldnews.component.ts


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


@Component({
    template: '<h1>World News Component</h1>'
})

export class WorldNewsComponent {

}

Then in the app folder we add the AppComponent and the main.ts. AppComponent is the root of the application, that hosts the client user experience. In main.ts we import 2 things to launch the app : Angular’s browser bootstrap function and the AppComponent.

app.component.ts


import { Component , OnInit } from '@angular/core';

import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated';


//components 
import {WorldNewsComponent} from './world/worldnews.component';
import {MoviesComponent} from './movies/movies.component';


@Component({
  selector: 'my-app',
  templateUrl: './app/startpage.html',
  directives: [ ROUTER_DIRECTIVES],
  providers : [ROUTER_PROVIDERS]
})

@RouteConfig([
  {
    path: '/worldnews',
    name: 'WorldNews',
    component: WorldNewsComponent,
    useAsDefault: true
  },
  {
    path: '/movies',
    name: 'Movies',
    component: MoviesComponent
  }
])


export class AppComponent {




}

main.ts


import { bootstrap }    from '@angular/platform-browser-dynamic';
import { AppComponent } from './app.component';

bootstrap(AppComponent);


As you can see in the app.component.ts we import Routing functionality.

The Angular router is a combination of multiple services (ROUTER_PROVIDERS), multiple directives (ROUTER_DIRECTIVES), and a configuration decorator (RouteConfig). We import them all together:

import { RouteConfig, ROUTER_DIRECTIVES, ROUTER_PROVIDERS } from '@angular/router-deprecated';

We also add directives and providers metadata arrays to include the router assets


@Component({
  selector: 'my-app',
  templateUrl: './app/startpage.html',
  directives: [ ROUTER_DIRECTIVES],
  providers : [ROUTER_PROVIDERS]
})

Last , we use the @RouteConfig decorator to assign a router to the component and configure that router with routes


@RouteConfig([
  {
    path: '/worldnews',
    name: 'WorldNews',
    component: WorldNewsComponent,
    useAsDefault: true
  },
  {
    path: '/movies',
    name: 'Movies',
    component: MoviesComponent
  }
])

We have 2 routes : WorldNews and Movies. WorldNews is the default one.

The final step is to add the startpage.html and the index.html. The startpage.html is added inside the app folder but the index.html is added inside the root folder. In case you are confused with the files and folders structure please look at the photo below :

filetree

startpage.html


<div class="page-header marginTop10" >
  <a [routerLink]="['WorldNews']"><h1 style="width:40% ;float:left">World news <small>in Angular 2</small></h1></a>
   <div style="float:left">
       <nav>
                
                    <a [routerLink]="['WorldNews']">World News</a>
                    <a [routerLink]="['Movies']">Movies</a>
       </nav>
  </div> 
  <a  style="float:right" href="http://developer.nytimes.com/" target="_blank"> 
  <img src="http://static01.nytimes.com/packages/images/developer/logos/poweredby_nytimes_150a.png">
  </a>
  <div class="clearfix"></div>
</div>

 <router-outlet></router-outlet>


index.html


<html>
  <head>
    <title>Angular 2 World News</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="stylesheet" href="styles.css">
    <!-- 1. Load libraries -->
     <!-- Polyfill(s) for older browsers -->
    <script src="node_modules/core-js/client/shim.min.js"></script>
    <script src="node_modules/zone.js/dist/zone.js"></script>
    <script src="node_modules/reflect-metadata/Reflect.js"></script>
    <script src="node_modules/systemjs/dist/system.src.js"></script>
    <!--required for ng2 bootstrap -->
    <script src="node_modules/ng2-bootstrap/bundles/ng2-bootstrap.min.js"></script>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet">
    <!--required for http -->
     <script src="node_modules/@angular/http/http.js"></script>
    <!-- reactive JS -->
    <script src="node_modules/rxjs/RX.js"></script>

    <!-- 2. Configure SystemJS -->
    <script src="systemjs.config.js"></script>
    <script>
      System.import('app').catch(function(err){ console.error(err); });
    </script>
  </head>
   <base href="/">
  <!-- 3. Display the application -->
  <body>
    <div class="container">
      <my-app>Loading...</my-app>
    </div>
  </body>
</html>



We have made the first step! Our simple Angular 2 app with 2 basic screens is ready.

moviesAngular2

Giorgos Basagiannis

I am a full stack engineer with broad technical skill set. I am passionate about developing high quality software that is scalable and easy to maintain. My main areas of interest include Microsoft Web & Cloud Technologies,JavaScript based frameworks,SharePoint and Office 365.

Leave a Reply

Your email address will not be published. Required fields are marked *