Developing a Front-End Single Page Application (SPA) with Angular 4, using Visual Studio Code

As part of this Article, we are going to perform 3 different things –

  1. Install Visual Studio Code, and set up the Development Environment for building the Front-End Angular 4 Application for a Blog Application (Backend to be provided by a RESTful API)
  2. Go about building the Angular 4 Application with explanation of its different modules and components and how they are all wired up together.
  3. Short demonstration of how the Angular 4 application may be debugged on Visual Studio Code, using its Google Chrome Extension
  1. Install Visual Studio Code, and set up the Development Environment for building the Front-End Angular 4 Application for a Blog Application (Backend to be provided by a RESTful API)

Visual Studio Code is currently one of the most preferred Editors for developing Angular Applications, and it can be downloaded from https://code.visualstudio.com/. Visual Studio Code supports Angular IntelliSense and code navigation out of the box.

Angular is a JavaScript based library developed by Google to develop modern User Interfaces for web applications. AngularJS was the first release of the Angular family, dating back in 2010. Since then, first Angular saw major upgrade with the release of Angular 2 in 2015, and then Angular 4 was released in 2016. For this article, we shall be developing an Angular 4 Single Page Application (SPA).

1Figure 1: Default Angular 4 Application hosted on local Node.JS server

We shall be using the Angular Command Line Interface (CLI) to automate and perform a lot of tasks during the development process. To install and use the command line interface as well as to run the Angular application server, we first need the Node.js JavaScript runtime and npm (the Node.js package manager) installed. npm is included with Node.js. Node.js can be downloaded from https://nodejs.org/en/

In order to test that Node.js and npm are correctly installed on the machine, one can type node --version and npm --version on the powershell terminal in Visual Studio Code.

  1. Go about building the Angular 4 Application with explanation of its different modules and components and how they are all wired up together.

The powershell terminal can be easily opened by navigating to View-> Integrated Terminal on Visual Studio Code.

2.png

Figure 2 : Opening the Integrated Terminal in Visual Studio Code

3.png

Figure 3 : Integrated Terminal – Option to add additional terminals

To install the Angular CLI, in a terminal or command prompt type:

++++++++++

npm install -g @angular/cli

++++++++++

 

This may take a few minutes to install.

We can now proceed to creating our Angular Application. For that shall first need to change directory with the command cd and move to right directory where we want to create the Angular 4 project.

++++++++++

Windows PowerShell

Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\Users\ranajoy121\source\repos\TheCoreBlog> ng new BlogFE

++++++++++++

BlogFE is the name of the folder for the application. This may take a few minutes to create the Angular application in TypeScript and install it's dependencies.

Next, we can run the Angular 4 application by navigating to the new project folder and typing ng serve to start the web server and open the application in a browser:

++++++++++

Windows PowerShell

Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\Users\ranajoy121\source\repos\TheCoreBlog> cd BlogFE

PS C:\Users\ranajoy121\source\repos\TheCoreBlog\BlogFE> ng serve

++++++++++++

We can now see "Welcome to app!!" on http://localhost:4200 in the browser. We'll leave the web server running while we look at the application with VS Code.

Inside the Angular 4 Project folder, we next need generate some components. The first component we create is blogs.

++++++++++

Windows PowerShell

Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\Users\ranajoy121\source\repos\TheCoreBlog> ng generate component blogs

++++++++++++

Each newly generated component in an Angular 4 Project shall create 4 different files. For this blogs component, they are 

  1. blogs.component.css (which contains the style elements needed for the corresponding component) ,
  2. blogs.component.html (contains all the html code that should represent the corresponding component),
  3. blogs.component.ts (the TypeScript file that is responsible for binding different parts of the component together, and also interacting other parts of the Angular 4 project),  and
  4. blogs.component.spec.ts. ( generated for unit testing purposes, and for this article, we have it deleted from project. )

Once done with the blogs component, we simply navigate to the blogs folder and similarly create three other components there. Namely, blog and blog-list and full-blog.

As can be seen, the default component of the Angular 4 project is app component. To be added, as soon as a new component is added to the project, app.module.ts file gets updated to import the newly created component and add it to the declarations array. So, below is how our app.module.ts now looks after adding the 4 components : blogs, blog, blog-list, and full-blog

import { BrowserModule } from '@angular/platform-browser';

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

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

import { HttpModule } from '@angular/http';

import { AppComponent } from './app.component';

import { BlogsComponent } from './blogs/blogs.component';

import { BlogComponent } from './blogs/blog/blog.component';

import { BlogListComponent } from './blogs/blog-list/blog-list.component';

import { FullBlogComponent } from './blogs/full-blog/full-blog.component';

@NgModule({

  declarations: [

    AppComponent,

    BlogsComponent,

    BlogComponent,

    BlogListComponent,

    FullBlogComponent

  ],

  imports: [

    BrowserModule,

    FormsModule,

    HttpModule

  ],

  providers: [],

  bootstrap: [AppComponent]

})

export class AppModule { }

We next create a folder named shared under blogs component, and create a model class named Blog.

++++++++++++

Windows PowerShell

Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\Users\ranajoy121\source\repos\TheCoreBlog\BlogFE\src\app\blogs\shared> ng generate class blog.model

++++++++++++

Once generated, we can change the name of the class from Blog.Model to Blog, and align its properties in line with the properties of the C# Blog Class in the backend API.

export class Blog {

            BlogId:number;  

            BlogName:string;

            BlogContent:string;

            BlogAuthor:string;

}

Once done with creating the Blog model class, we next create a blog service class at the same folder location within the Angular 4 project.

++++++++++++

Windows PowerShell

Copyright (C) 2016 Microsoft Corporation. All rights reserved.

PS C:\Users\ranajoy121\source\repos\TheCoreBlog\BlogFE\src\app\blogs\shared> ng generate service blog

++++++++++++

The BlogService class is what binds different components of the Angular project together. The @injectable directive before the declaration of the class name enables Dependency Injection through which different properties and methods BlogService can be directly referred to/ called from other Component classes.

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

import { Http, Response, Headers, RequestOptions, RequestMethod } from '@angular/http';

import { Observable } from 'rxjs/Observable';

import 'rxjs/add/operator/map';

import 'rxjs/add/operator/toPromise';

import {Blog} from './blog.model'

@Injectable()

export class BlogService {

  //adding a new property for the service

  selectedBlog : Blog;

  draftBlog : Blog;

  blogList : Blog[];

  showSelected: boolean;

  constructor(private http : Http) {

    this.showSelected = false;

    this.draftBlog =  {

      BlogId: Math.floor(Math.random() * 1000),

      BlogName: '',

      BlogAuthor: '',

      BlogContent: ''

     

    }

   }

  postBlog(blog : Blog){

    var body = JSON.stringify(blog);

    var headerOptions = new Headers({'Content-Type':'application/json'});

    var requestOptions = new RequestOptions({method : RequestMethod.Post,headers : headerOptions});

    return this.http.post('https://localhost:44337/api/Blog1',body,requestOptions).map(x => x.json());

  }

  putBlog(id, blog) {

    var body = JSON.stringify(blog);

    var headerOptions = new Headers({ 'Content-Type': 'application/json' });

    var requestOptions = new RequestOptions({ method: RequestMethod.Put, headers: headerOptions });

    return this.http.put('https://localhost:44337/api/blog1/' + id,

      body,

      requestOptions).map(res => res.json());

  }

  getBlogList(){

    this.http.get('https://localhost:44337/api/blog1')

    .map((data : Response) =>{

      return data.json() as Blog[];

    }).toPromise().then(x => {

      this.blogList = x;

    })

  }

  deleteBlog(id: number) {

    return this.http.delete('https://localhost:44337/api/blog1' + id).map(res => res.json());

  }

}

As can be seen inside the BlogService class, we have created the four methods for performing the standard CRUD operations, consuming the RESTFul API accessible at https://localhost:44337/api/blog1

 

Of course the import statements before the declaration of the BlogService class are also worth noting, for without them the methods to consume the RESTful API can’t be implemented.

Let us now take a quick look into one of the Component classes to understand how the BlogService is getting consumed through Dependency Injection. We have the code of blog.component.ts below. As can be seen, a local variable as a parameter in the constructor is used to reference the BlogService, and then that can be used anywhere within the BlogComponent class later to consume the various properties and methods provided by the BlogService.

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

import {BlogService} from '../shared/blog.service';

import { NgForm } from '@angular/forms'>

@Component({

  selector: 'app-blog',

  templateUrl: './blog.component.html',

  styleUrls: ['./blog.component.css']

})

export class BlogComponent implements OnInit {

  constructor(private blogService : BlogService)   {  }

  ngOnInit() {

    this.resetForm();

  }

  resetForm(form?: NgForm) {

    if (form != null)

      form.reset(); 

  }

  onSubmit(form: NgForm) {

    if (form.value.BlogId == null)

    {

      this.blogService.postBlog(form.value)

      .subscribe(data => {

        this.resetForm(form);

        this.blogService.getBlogList();

      }

      )

   

    }

    else {

      this.blogService.putBlog(form.value.BlogId, form.value)

      .subscribe(data => {

        this.resetForm(form);

        this.blogService.getBlogList();

       

      });

    }

  }

 

}

4.png

Figure 4 : Structure of the Angular 4 Project BlogFE

Since Angular 4 applications are all Single-Page-Applications (SPA), managing the placement of the different components within the view is central to how the application functions. In this case, blogs.component.html is the html file of the first component we created - which in turn shall conditionally contain other components as and when required by the application. Local as well as BlogService methods and properties have been used by  this component. The angular directive *ngIf is what checks for a particular condition. 

blogs.component.html

<div style="text-align:center">

 

    The Core Blog

 

</div>

<button (click)="showNewBlog()" class="newblog" >Add a new Blog</button>

<div *ngIf=showNew style="width:800px; margin:20 auto;">

 

     

     

 

</div>

<button *ngIf=showNew (click)="hideNewBlog()">Discard Draft!</button>

<div *ngIf=blogService.showSelected style="width:800px; margin:20 auto;">

 

   

</div>

<button *ngIf=blogService.showSelected (click)="displayAllBlogs()">Show all blogs!</button>

<div *ngIf=!blogService.showSelected style="width:800px; margin:20 auto;">

       

    

   

</div>

blogs.component.ts

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

import {BlogService} from './shared/blog.service'

@Component({

  selector: 'app-blogs',

  templateUrl: './blogs.component.html',

  styleUrls: ['./blogs.component.css'],

  providers: [BlogService]

})

export class BlogsComponent implements OnInit {

  showNew : boolean;

  constructor( private blogService : BlogService) {  this.showNew = false;}

  ngOnInit() { }

  showNewBlog(){  this.showNew = true; }

  hideNewBlog(){  this.showNew = false; }

  displayAllBlogs(){   this.blogService.showSelected = false; }

}

Let us now look at how the component  works.

Blog-list.component.html

<br>

Existing Blogs

<hr>

   

 

     

{{blog.blogName}}

     

{{blog.blogContent}}...

      <a  (click)="displayFullBlog(blog)">

       

     

     


   

As can be seen, the html file of the blog-list component uses a *ngFor directive to create a list or repetition of all the Blog Items available at the backend (which are loaded into the blogList property of BlogService class when it’s first loaded). Keeping a property within {{ }} is what creates a 2-way databinding in Angular 4.

Blog-list.component.ts

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

import {BlogService} from '../shared/blog.service';

import { NgForm } from '@angular/forms'>

import {Blog} from '../shared/blog.model'

import { Observable } from 'rxjs/Observable';

@Component({

  selector: 'app-blog-list',

  templateUrl: './blog-list.component.html',

  styleUrls: ['./blog-list.component.css']

})

export class BlogListComponent implements OnInit {

  constructor(private blogService : BlogService) {

   

   }

  ngOnInit() {

         this.blogService.getBlogList();   

  }

  displayFullBlog(b: Blog) {

    this.blogService.selectedBlog = Object.assign({}, b);

    this.blogService.showSelected = true;

  }

 

}

How the blog component and full-blog component works is also similar. On interest, the full codebase of this Angular demo project (along with the backend API project built using ASP.NET Core 2.0) can be accessed on GitHub.

  1. Short demonstration of how the Angular 4 application may be debugged on Visual Studio Code, using its Google Chrome Extension

While there are other options for debugging an Angular 4 application during Development, a highly recommended way is debugging directly at Visual Studio Code, using  Debugger for Chrome extension.

Open the Extensions view (Ctrl+Shift+X) in Visual Studio Code and type 'chrome` in the search box. You'll see several extensions which reference Chrome.

5.png

Press the Install button for Debugger for Chrome. The button will change to Installing then, after completing the installation, it will change to Reload. Press Reload to restart VS Code and activate the extension.

Setting a breakpoint :

To set a breakpoint in app.component.ts, click on the gutter to the left of the line numbers. This will set a breakpoint which will be visible as a red circle.

6.png

Configure the Chrome debugger

We need to initially configure the debugger. To do so, go to the Debug view (Ctrl+Shift+D) and click on gear button to create a launch.json debugger configuration file. Choose Chrome from the Select Environment dropdown. This will create a launch.json file in a new .vscode folder in your project which includes configuration to both launch the website or attach to a running instance.

We need to make one change for our example: change the port from 8080 to 4200. Your launch.jsonshould look like this:

{

   // Use IntelliSense to find out which attributes exist for C# debugging

   // Use hover for the description of the existing attributes

   // For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md

   "version": "0.2.0",

   "configurations": [

     

    {

        "type": "chrome",

        "request": "launch",

        "name": "Launch Chrome against localhost",

        "url": "http://localhost:4200",

        "webRoot": "${workspaceFolder}"

    },

    {

        "type": "chrome",

        "request": "attach",

        "name": "Attach to Chrome",

        "port": 9222,

        "webRoot": "${workspaceFolder}"

    }

]

}

With breakpoints set, we just need to hit F5 or press the Play button in the debug view in VS Code in Debug Mode. It will fire up a new instance of Chrome, and shall direct to the file in the Angular 4 project where a breakpoint has been hit.  

 

7.png

 

In the debug mode, on the left pan of the screen, where the details of the local variables and properties can be visualized. On top, there’s options to Step Into, Step Over, Step Out, Continue, Restart, or Stop.

 

8.png

  • Erstellt am .

Standorte

Region Nord: Hamburg, Emden
Region Mitte: Langenfeld, Offenbach am Main
Region Ost: Leipzig
Region Süd: München, Ulm
Copyright by Orange Networks GmbH