Data Binding in Angular

Data binding is the synchronization of elements of the component UI widget to the data in your component classes, and vice versa, managed by Angular. It allows communication between template and components class. Data binding can be one way or two-way data binding.

With data binding, we can control the user interface of our components by changing variables, and we can accept user input, allowing them to change the value of some variables. Data binding can control every aspect of the user interface: hiding things, closing things, showing results, accepting user input, and more. It’s incredibly powerful and easy to use.

1. One Way Data binding: This can occur when the template (the View) is automatically kept up-to-date with the latest values in the class instance variables (the Model). Updates flow in only one direction.

One-Way Data Binding wit {{ and }} Those double curly braces are also known as mustaches or interpolation. The double curly braces are used for one-way binding a template expression, making a calculation from available data in the Model and including it in the View. The expression produces a value, and it’s included in the View (the markup from the component template). The Model—that is, the data in the Component class—is never updated

Create simple angular app – change the value of the app.component.ts file to

import { Component } from '@angular/core';
@Component({
  selector: 'app-root',
  template: `
  <h1>
    {{ name }}
  </h1>
  <p>
    Length: {{ name.length}}
  </p>
  <p>
    Reversed: {{getAge()}}
  </p>
 `,
  styles: []
})
export class AppComponent {
  name = 'John Smith';
  dob = 1997;

getAge(){
    return 2018-1997;
  }
}

One-Way Data Binding with [ and ] or *
The square braces OR * can be used for one-way binding. With [] we can bind a template expression, making a calculation from available data in the Model and including it in the data binding target.
[Data Binding Target] = “Template Expression”
Or:
*Data Binding Target = “Template Expression”
The data binding target with * is something in the DOM (including element properties, component properties, and directive properties) that can be bound to the result of the expression on the right side of the target, as shown in.

The ng-template directive and ngIf

The ng-template directive allows us to run a set of HTML tag block based on ngIf|else condition. TemplateRef is the class name and <ng-template> is the html tag — they are both referencing the same thing.

We can use <ng-template> with ngFor, ngIf and ngSwitch. Using TemplateRef and ViewContainerRef we can reuse the code of
<ng-template> in our HTML template. <ng-template> example with ngFor is as follows.

<ng-template ngFor let-person [ngForOf]= "allPersons" let-i="index">
<p>{{i + 1}}. {{person.name}} : {{person.age}} </p>
</ng-template>

In Angular allow us to use ng-template with if/else scenario below example.

<div>
       <div *ngIf="photoID; then govId else newGovId" class="govID"></div>
        <ng-template #govId>
          <ion-item>
            <h2>Government Identity Card </h2>
              <img src={{photoID}}>
            <br/>
            <div class="gov-id">
              <label for="file">Edit Government ID</label>
              <input type="file" class="custom-file-input" (change)="detectGovtIdFile($event)">
            </div>
          </ion-item>
        </ng-template>
        <ng-template #newGovId>
          <ion-item>
            <input type="file" class="custom-file-input" (change)="detectGovetIdFile($event)">
          </ion-item>
        </ng-template>
 </div>

A simpler version of ngIf and else template

We can used platform variable of Platform services directly into template. To check if plaftform is android or not.
<div ngIf= "platform.is('android'); then truecondition else falseCondition">
or 
<div *ngIf="searchResults;  else elseBlock">

</div> // End of true Condition
<ng-template #elseBlock>

</ng-template>

Bootstrap components in Angular (ng-bootstrap)

The ng-bootstrap, allow us to use Bootstrap Components and directive in Angular 4+ through ng-bootstrap. This makes it easy to use Bootstrap in your Angular apps.

Angular 4+ is required to use ng-bootstrap. ng-bootstrap depends on Bootstrap’s CSS being available, but you don’t need the Bootstrap JS or jQuery dependencies.

As the Bootstrap 4 contains many different JavaScript-dependent components. Many of these components rely on jQuery for Document Object Model (DOM) manipulation and can adversely interact with Angular’s own View Encapsulation based data-binding. We will solve this issue using the Angular friendly versions of these components provided by the ng-bootstrap project.

Step 1: Install the bootstrap through npm

To get started with Bootstrap in our Angular project, we will first have to install it as a dependency:
     $ npm install –save bootstrap@next
The @next will install the latest version of Bootstrap 4 and not the bootstrap 3 stable version.

Step 2: Importing bootstrap CSS or SCSS file

Once we have installed Bootstrap, we have to import our bootstrap scss file in own Sass modules. We simply add an import statement to the top of our /src/styles.scss file in our Angular project:

@import ‘~bootstrap/scss/bootstrap’;

This imports all of the Bootstrap using a special loader mechanism provided by sassloader. Our Angular application now has all of the Bootstrap 4 CSS framework available and ready to use.

Or

We can import our bootstrap CSS file in style.css of our angular project as

@import “~bootstrap/dist/css/bootstrap.css”

To make the Bootstrap CSS classes available for the components in our project we need to include the Bootstrap CSS file from node_modules/bootstrap/dist/css/bootstrap.css in our project.

Or

We have another option of importing our bootstrap file by  just add the following code in the styles array of the .angular-cli.json file:

“../node_modules/bootstrap/dist/css/bootstrap.min.css”,

Step 3: We have to import our ng-bootstrap module in app.module.ts file

import {NgbModule} from '@ng-bootstrap/ng-bootstrap';
....
  imports: [
    BrowserModule,
    NgbModule.forRoot()
  ],

})
export class AppModule { }

 

Step 4: Use the ng-bootstrap Component

Now that we have imported both Bootstrap-4 and ng-bootstrap module in our apps, we can use any of ng-bootstrap components it provides to us. Let’s add some of ng-bootstrap component : 

Add the following code in app.component.html file

<div class="jumbotron">
  <div class="container text-center">
    <ngb-alert type="success" [dismissible]="false">
      ng-bootstrap Working
    </ngb-alert>

    <h1>
      <i class="fa fa-bath" aria-hidden="true"></i>
      Bootstrap jumbotron
    </h1>
  </div>
</div>


<p>
  <ngb-alert [dismissible]="false">
    <strong>Warning!</strong> Better check yourself, you're not looking too good.
  </ngb-alert>
</p>

<div class="container">
  <p>
    A progress bar:
    <ngb-progressbar showValue="true" type="warning" [value]="85">
    </ngb-progressbar>
  </p>
</div>
<br/><br/>
<div class="container">
    <p>Popup box</p>
    <button type="button" class="btn btn-outline-secondary" placement="top"
    ngbPopover="Vivamus sagittis lacus vel augue laoreet rutrum faucibus." popoverTitle="Popover on top">
      Popover on top
    </button>
</div>
<div class="container">
  <p>Rating</p>
  <ngb-rating [(rate)]="currentRate"></ngb-rating>
  <hr>
  <pre>Rate: <b>{{currentRate}}</b></pre>
</div>



Angular CRUD operation on Firebase

We can use Firebase to store data. With Firebase we can easily do CRUD and it provides login with the different option. We are creating an Angular book app with firebase through package angularfire2.  We will be doing following as

  1. We insert/deleting/editing a book record and display all the book on our page.
  2. We are using CDN of Bootstrap 4 and font awesome in index.html of src file.

App Screenshot of our an Angular book apps

Step 1: Adding the following CDN font-awesome and bootstrap

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.6/css/bootstrap.min.css" integrity="sha384-rwoIResjU2yc3z8GV/NPeZWAv56rSmLldC3R/AZzGRnGxQQKnKkoFVhFQhNUwEyJ" crossorigin="anonymous">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css">

 

Step 2:  Setup the project and Installing the required Plugin

We have to install angularfire2 package to use the power of RxJS, Angular, and Firebase. to perform realtime CRUD operation on Firebase server.

npm install firebase angularfire2 --save

Here we are creating the main component called books-component containing (book-component and book-list-component) and share folder containing model and service. File structure of our Angular book apps

Here we will be creating our book component and services as follow

ng g c books

We will creating child component in cd src/app/books/
ng g c book
ng g c book-list

create shared folder in book component containing book model and service
ng g class book.model
ng g s book

Add the following code for book model in app/books/shared/book.model.ts

export class Book{
    $key : string;
    bookname : string;
    author : string;
    genre : string;
    price : number;
}

Add the following code for book service in app/shared/book.service.ts

import { Injectable } from '@angular/core';
import { AngularFireDatabase, AngularFireList } from 'angularfire2/database';
import { Book } from './book.model';

@Injectable()
export class BookService {

  bookList: AngularFireList<any>;
  selectedBook : Book = new Book();
  
  constructor(private firebase: AngularFireDatabase) {}

  getData(){
    this.bookList = this.firebase.list('books');
    return this.bookList;
  }

  insertBook(book : Book){
    this.bookList.push({
      bookname : book.bookname,
      author : book.author,
      genre : book.genre,
      price : book.price,
    })
  }

  updateBook(book : Book){
    this.bookList.update(book.$key, {
      bookname : book.bookname,
      author : book.author,
      genre : book.genre,
      price : book.price,
    })
  }

  deleteBook(key : string ){
    this.bookList.remove(key);
  }

}

 

In app/books component we have to import to book service provider. Add the following code in app/books.component.html file, here we are adding both the child component tag, one component to display the book form and other component to display the list of all book from firebase database.

<div  class="jumbotron">
  <h2 style="text-align:center;">
    Book Collection
  </h2>
</div>
<div class="container">
  <div class="row">
    <div class="col-md-7">
      <app-book></app-book> 
    </div>
    <div class="col-md-5">
      <app-book-list></app-book-list>
    </div>
  </div>
</div>

Add the following code in app/books.component.ts file

import { Component, OnInit } from '@angular/core';
import { BookService } from './shared/book.service';

@Component({
  selector: 'app-books',
  templateUrl: './books.component.html',
  styleUrls: ['./books.component.css'],
  providers: [ BookService]
})
export class BooksComponent implements OnInit {

  constructor(private bookService : BookService) { }

  ngOnInit() {
  }

}



Step 3: Adding code to child component

In books component we have two child component, first we will add code to child book-component to display the form. Add the following code in app/books/book/book-component.ts file

<form #bookForm="ngForm" (ngSubmit)="onSubmit(bookForm)">
  <input type="hidden" name="$key" #$key="ngModel" [(ngModel)]="bookService.selectedBook.$key">
  <div class="form-group">
    <label>Book Name</label>
    <input class="form-control" name="bookname" #name="ngModel" [(ngModel)]="bookService.selectedBook.bookname" placeholder="Book Name" required>
  </div>

  <div class="form-group">
    <label>Author</label>
    <input class="form-control" name="author" #name="ngModel" [(ngModel)]="bookService.selectedBook.author" placeholder="Author" required>
  </div>

  <div class="form-group">
    <label>Genre</label>
    <select class="form-control" name="genre" #name=ngModel [(ngModel)]="bookService.selectedBook.genre" >
      <option value="Novel">Novel</option>
      <option value="Non Fiction">Non Fiction</option>
      <option value="Biography">Biography</option>
    </select>
  </div>

  <div class="form-group">
    <label>Price</label>
    <div class="input-group">
      <div class="input-group-addon">
        <i class="fa fa-inr"></i>
      </div>
      <input class="form-control" name="price" #name="ngModel" [(ngModel)]="bookService.selectedBook.price" placeholder="Price" required>
    </div>
  </div>

  <div class="form-group">
    <button type="submit" class="btn btn-default" [disabled]="!bookForm.valid" >
      <i class="fa fa-floppy-o" aria-hidden="true"></i> Submit</button>
    <button type="button" class="btn btn-default" *ngIf="bookService.selectedBook.$key != null" 
      (click)="onDelete(bookForm)">
      <i class="fa fa-trash"></i> Delete</button>
    <button type="button" class="btn btn-default" (click)="resetForm()">
      <i class="fa fa-repeat"></i> Reset</button>
  </div>
</form>

Add the following code in app/books/book/book-component.ts file

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

import { BookService} from '../shared/book.service';

@Component({
  selector: 'app-book',
  templateUrl: './book.component.html',
  styleUrls: ['./book.component.css']
})
export class BookComponent implements OnInit {

  constructor(private bookService : BookService) { }

  ngOnInit() {
    this.resetForm();
  }

  onSubmit(form : NgForm){
    if(form.value.$key == null)
      this.bookService.insertBook(form.value);
    else
      this.bookService.updateBook(form.value);
    this.resetForm(form);
  }

  resetForm(form? : NgForm){
    if(form != null)
      form.reset();

    this.bookService.selectedBook = {
      $key : null,
      bookname : '',
      author : '',
      genre : '',
      price : 0,
    }
  }
  onDelete(form : NgForm ){
    if(confirm('Are you sure to delete this record ?') == true) {
      this.bookService.deleteBook(form.value.$key);
      this.resetForm(form);
    }
  }

}

In onSubmit() we have if condition to determine whether we are inserting new record or editing existing data. If a value of the variable $key is null this means we are inserting new record otherwise we are calling updateBook methods of service to edit the existing record.

In book-list component, in this child component, we are displaying the book detail information on the page. In app/books/book-list/book-list.component.html add the following code.

<ul class="list-group hover">
  <h4>Book Name - Author - Genres</h4>
  <li class="list-group-item" *ngFor="let book of bookList" (click)="onItemClick(book)">
    {{book.bookname}} - {{book.author}}  : {{book.genre}}
  </li>
</ul>

In app/books/book-list/book-list.component.ts add the following code.

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

import { BookService } from '../shared/book.service';
import { Book } from '../shared/book.model';

@Component({
  selector: 'app-book-list',
  templateUrl: './book-list.component.html',
  styleUrls: ['./book-list.component.css']
})
export class BookListComponent implements OnInit {

  bookList: Book[];
  
  constructor(private bookService : BookService) { }

  ngOnInit() {
    var x = this.bookService.getData();
    x.snapshotChanges().subscribe(item => {
      this.bookList = [];
      item.forEach(element => {
        var y = element.payload.toJSON();
        y["$key"] = element.key;
        this.bookList.push(y as Book);
      })
    })
  }

  onItemClick(book : Book){
    this.bookService.selectedBook = Object.assign({}, book);
  }

}

Note :  We have onItemClick(book : Book){ this.bookService.selectedBook=Object.assign({}, book); } selected red line of book-list.component.ts code should be same as code of form element of book.component.hmtl as <inputclass=”form-control”name=”bookname” #name=”ngModel” [(ngModel)]=”bookService.selectedBook.bookname” placeholder=”Book Name”required> When we click on one of book-list on page will automatically add to the form element, so that we can easily modifed the exiting book record.

Step 4:  We have to add following code in firebase setup code in environments/environment.ts  

export const environment = {
  production: false,

  firebaseConfig : {
    apiKey: "AIzaSyA1KzVfeo9yE6OyQiNrBx2MBvMVxVngctI",
    authDomain: "bookangular-d47f9.firebaseapp.com",
    databaseURL: "https://bookangular-d47f9.firebaseio.com",
    projectId: "bookangular-d47f9",
    storageBucket: "bookangular-d47f9.appspot.com",
    messagingSenderId: "572743007724"
  }
};

At last, we have to register the provider for angularfire2 plugin, form module and we also have to add reference of all component in app/app.module.ts file.

import { AngularFireModule } from 'angularfire2';
import { AngularFireDatabaseModule } from 'angularfire2/database';
import { FormsModule } from '@angular/forms';

import { AppComponent } from './app.component';
import { BooksComponent } from './books/books.component';
import { BookComponent } from './books/book/book.component';
import { BookListComponent } from './books/book-list/book-list.component';
import { environment} from '../environments/environment';

@NgModule({
  declarations: [
    AppComponent,
    BooksComponent,
    BookComponent,
    BookListComponent
  ],
  imports: [
    BrowserModule,
    AngularFireModule.initializeApp(environment.firebaseConfig),
    AngularFireDatabaseModule,
    FormsModule,
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

 

Add the CSS code for book apps in style.css in src folder, here we are adding hand cursor on the book list and button.

/* You can add global styles to this file, and also import other style files */
input.ng-invalid.ng-dirty{
    border: 1px solid red;
}


button, ul.list-group.hover li.hover{
    cursor: pointer;
}

Angular Reactive Form

In previous we have learned, the template drives forms, in a template-driven from where most of our logic, validation, controls are in template or HTML form. We are applying ngModel and other an Angular directive in template and template drive form is suitable for building the simple form with basic validation(required, minlength, maxlength).

Whereas in case of modal driven (Reactive form):  forms, all the control and logic validation of form are defined in your component typescript file. With the model-driven approach, we create form from the instance of FormGroup and the FormBuilder instance allows us to specify form controls and the various validations on the input element of the form in the component. The model drive form is the best choice for creating a complex form, it provides the developer with more control on the form.

In this example, we are learning

  1. How to build a reactive form with custom validation
  2. Apply select form element value from external sources.
  3. Displaying custom error message for each form element error related to validation.

We will make simple reactive form example, we have to follow these step to complete our task.

Step 1: Define reactiveForm module in app.module.ts file

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

imports: [
   ReactiveFormsModule
],

Step 2: Define Form validation in app.component.ts

We will define the form model on from an instance of FormGroup and we will uses form validation from FormBuilder instance. We have to import FormGroup and FormBuilder provider from ‘@angular/form’.

We are defining separate error message for each element validation by define property element in the component and assigning the error message through method called initializeErrorMessages.  Add the following code in app.component.ts file.

import { Component, OnInit } from '@angular/core';
import { FormGroup, FormBuilder, Validators } from '@angular/forms';
import { TamoDepartment } from './model/department.interface';
import { MockDepartment } from './data/mockDepartment';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})

export class AppComponent implements OnInit{
  public title: string  = 'Angular Reactive Form';
  public formTamo : FormGroup;

  departments: any[];
  titleErrorMessage: string;
  descriptionErrorMessage : string;
  categoryErrorMessage: string;

  constructor(private formBuilder: FormBuilder){
    this.displayDepartments();
  }

  ngOnInit(){
    this.formTamo = this.formBuilder.group({
      "title": [null, Validators.required],
      "description": [null, [Validators.required, Validators.minLength(10), Validators.maxLength(50)]],
      "category" : [null]
    })
  }

  displayDepartments(){
    this.departments = MockDepartment;
    this.initializeErrorMessages();
  }
  
  initializeErrorMessages(){
    this.titleErrorMessage = "This is required";
    this.descriptionErrorMessage ="Description should be of minimum 10 and maximun 50 characters";
    this.categoryErrorMessage = "Category is required";
  }
}

We can assign the value of the form select element department option value from the external data in file app/data /mockDepartment.ts

app/model/department.interface.ts

export interface TamoDepartment{
    id:number,
    name: string,
    description: string
}

In app/data/mockDepartment.ts we have to define the list of department name to array element TamoDepartment[]

import { TamoDepartment } from '../model/department.interface';

export const MockDepartment : TamoDepartment[] = [
    {
        id: 0,
        name: 'Designing',
        description: 'Photoshop, Indesign'
    },
    {
        id: 1,
        name: 'Web Developer',
        description: 'Web through Node and Angular'
    },
    {
        id: 3,
        name: 'Hybrid App Developer',
        description: 'Through Ionic'
    },
    {
        id: 3,
        name: 'Android Developer',
        description: 'The 140 Android App developed'
    },   
    {
        id: 4,
        name: 'IOS Developer',
        description: 'Lastest ISO'
    }
]

 

Step 3:  Define form in app.component.html

Note: We have to assign form name (formTamo) to an Angular directive [fromGroup] and we are also assigning department select element list value from external data.

<div class="container">
  <h1> {{title}} </h1>
  <div class="card">  
    <div class="card-block">
      <form [formGroup]="formTamo" (ngSubmit)="submitDetails(formTamo.value)">
        <div class="form-group">
          <label>Title :</label> 
          <input type="text" class="form-control" formControlName="title" />
          <div class="alert alert-danger" *ngIf="!formTamo.controls['title'].valid && formTamo.controls['title'].touched" >
            {{ titleErrorMessage }}
          </div>
        </div>

        <div class="form-group">
          <label>Description :</label> 
          <textarea class="form-control" formControlName="description"></textarea>
          <div class="alert alert-danger" 
            *ngIf="!formTamo.controls['description'].valid && formTamo.controls['description'].touched" >
              {{ descriptionErrorMessage  }}
            </div>
        </div>

        <div class="form-group">
          <label>Department :</label> 
          <select class="form-control" formControlName="category">
            <option *ngFor ="let item of categories" value="{{item.name}}">{{item.name}}</option>
          </select>
        </div>
        <button class="btn btn-primary btn-block">Submit</button>
      </form>
    </div>
    <p>Form Element : {{formTamo.value | json}}</p>
  </div>

</div><!-- End of container div -->

Angular Form

We can create a form in Angular through form tag of HTML and Angular allow us to add additional control the form through its new directive like ngForm, ngModel, and ngModelGroup features. Angular allows us to create a form in two different approaches and each had its own an Angular Module as
1. Template drive form (FormsModule)
2. Reactive form (ReactiveFormsModule)

Note The both type of the form we have common building blocks as FormControl, FormGroup, and FormArray.

In this an example, we  will walk through

  • How to set up your forms
  • How to use different Data binding in an Angular Form
  • Form validation, and styling.
  • Learning the ngModelGroup Directive

Angular allows us to use ngModel in two different data binding

  1. We can use one-way data binding through
    <input type=”email”name=”email”class=”form-control” ngModel>
  2. We can use two-way data binding [(ngModel)] called a banana in the box structure.
         <input type="email" name="email" class="form-control" [(ngModel)]="emailAddress">
          {{ emailAddress }}

Applying style to Angular Form 

When we are using a form in an Angular, Angular will add number class to the form, as

  1. isTouched  (Check form element is touched or not)- ng-untouched or ng-touched.
  2. is value change (Check the form element value change or not)- ng-pristine ng-dirty.
  3. is Invalide (Check the input value type or not with the use of required attribute) – ng-valid invalid

In this example, we apply the CSS style to input text through a form element class provided by an Angular. We can use an Angular ng-valid class to apply the CSS style to the input of the form and we can apply the style to the input text of firstName with required attribute through an Angular ng-invalid class.

Add the following code in app.component.html

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styles:[`
		input.ng-invalid {
			border-left: 5px solid red;
		}
		input.ng-valid {
			border-left: 5px solid blue;
		}
	`]
})
export class AppComponent {
  public title : string = 'Angular - 4 Form Example';
  public firstName : string = 'Initial Name';

Add the following code in app.component.ts file

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styles:[`
		input.ng-invalid {
			border-left: 5px solid red;
		}
		input.ng-valid {
			border-left: 5px solid blue;
		}
	`]
})
export class AppComponent {
  public title : string = 'Angular - 4 Form Example';
  public firstName : string = 'Initial Name';

}

 

ngModelGroup Directive
The ngModelGroup, we can use this directive if we like to create a sub-group within a form. This can come in handy if you want to validate a sub-group of your form separately from the rest of your form, or if some values in your domain model make more sense to consume together in a nested object.

In this an example, we will make a form with an Angular directive ngForm, ngModel, and ngModelGroup.

Note: We have to register FormsModule module in app.module.ts from ‘@angular/forms’;

Step 1: Add the code for form app.component.html

<div class="container">
  <h1> {{title}} </h1>
  <form #profileForm="ngForm" (ngSubmit)="onSubmit(profileForm.value)"> 
    <div class="form-group">
      <label>First Name </label>
       <input type="text" #fnameField name="fName" class="form-control" ngModel>
    </div>
    <div class="form-group">
      <label>Last Name : </label>
      <input type="text" name="lName" class="form-control" ngModel>
    </div>
    <div class="form-group">
      <label>Email : </label>
      <input type="email" name="email" class="form-control" [(ngModel)]="email">
    </div>
    <div ngModelGroup="address">
      <div class="form-group">
        <label>Address : </label>
        <input type="text" name="address" class="form-control" ngModel>
      </div>
      <div class="form-group">
        <label>City : </label>
        <input type="text" name="city" class="form-control" ngModel>
      </div>
      <div class="form-group">
        <label>Country</label>
        <select class="form-control" name="country" ngModel>
          <option value="india">India</option>
          <option value="france">France</option>
          <option value="germany">Germany</option>
          <option value="japan">Japan</option>
          <option value="Mongolia">Mongolia</option>
        </select>
      </div>
    </div>
    <div class="form-group">
      <label>Gender</label>
      <input type="radio" name="sex" class="form-control" value="Male" ngModel>Male
        <input type="radio" name="sex" class="form-control" value="Female" ngModel> Female
    </div>
    <div class="form-group">
      <br/><br/>
      <input class="btn btn-primary" type="submit">
    </div>
  </form>

  <div>{{profileForm.value | json }}</div>
</div><!-- End of container div -->

 

Step 2: Add the code in app.component.ts  

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

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  public title : string = 'Angular - 4 Form Example';

  public onSubmit( data: any){
    console.log('Data', data);
  }
}

Angular HTTPClient Module

Angular 4.3  introduce HTTP client module to request a call to HTTP request. We can define HTPP request in Services, services are user-defined classes used to access database and  from server site and other activities.  The front-end can’t make request directly to database because of security issue. Angular recommends only having template specific codes in components. A component’s responsibility is to enrich the UI/UX in the Angular application and delegate business logic to services. Components are consumers of services:

This new module is available in package @angular/common/http and a complete re-implementation of the former HttpModule. The new HttpClient service is included in HttpClientModule and can be used to initiate HTTP request and process responses within your application.

Application-specific or business logic such as persisting application data, logging errors, and file storage should be delegated to services, and components should consume the respective services to deal with the appropriate business or application-specific logic.

The httpClientModule is upgraded version of http from @angular/http module with the following improvements:

  • Typed, synchronous response body access, including support for JSON body types
  • JSON is an assumed default and no longer needs to be explicitly parsed
  • Interceptors allow middleware logic to be inserted into the pipeline
  • Immutable request/response objects
  • Progress events for both request upload and response download
  • Post-request verification & flush based testing framework

In this example we will learn

  1. How to use new HTTP Client Module
  2. The ngModel, bi direction data binding

Screen shot of our apps.

Step 1: Project Setup

ng new httpClient

We have to import our new Angular 4.3 HttpClient module

import {HttpClientModule} from '@angular/common/http';

imports: [
    HttpClientModule,
    FormsModule
  ],

 

Step 2: Create a service to request HTTP request

We have to create a service class to request HTTP request to a remote server or site restcountries.eu to retrieve information about the a country. In our case we will create countries. http. service. this file in app/services folder. We have to create service folder and add the following code in app/services/countries.http.service.ts

Note : We have to import HttpClient from HttpClientModule and inject the HttpClient dependency in constructor.

import { Injectable } from '@angular/core';
import { Http } from '@angular/http';
import { HttpClient } from '@angular/common/http';

@Injectable()
export class CountriesService {

  constructor(private _http: HttpClient) { }

  public getCountryDetail(countryName : string){
    let _url: string = 'https://restcountries.eu/rest/v2/name/'+countryName+'?fullText=true';
    return this._http.get(_url);
  }

  public getCountries(){
    let _url: string = 'https://restcountries.eu/rest/v2/all';
    return this._http.get(_url);
  }
}




Step 3: Modify the app.component.ts file

In app.component we will add input box and selection option to add or select the country from the countries list. Both input box and selection box are linked into single ngModel variable countryName in typescript file.

Add the following code in app.component.html file.

<input type='text' [(ngModel)]="countryName">
<select [(ngModel)]="countryName">
    <option *ngFor = "let country of countriesList" value="{{country.name}}">
        {{country.name}}
    </option>
</select>
<button (click)="getCountryInfo(countryName)">Get Country Details</button><br/><br/>
<h1>{{ title }}</h1>
<h3>Name : {{ countryObj.name }}</h3>
<h3>Capital : {{ countryObj.capital }}</h3>
<h3>Currency : {{ countryObj.currencies[0].code}}</h3>
<img src="{{ countryObj.flag }}" width="400" height="300">

How to add HighChart in Angular

The HighChart and D3 are the Javascript library for data visualization. We have a lot of other libraries option to add a chart in Angular. Where D3 is the most popular open source and Highcharts is a product that was created by the Norway-based company, Highsoft.

Highcharts is an SVG-based, multi-platform charting library that has been actively developed since 2009. It makes it easy to add interactive, mobile-optimized charts to your web and mobile projects. It features robust documentation, advanced responsiveness and industry-leading accessibility support.

In this example, we will allow the user to add a random point on the chart through a button on the browser, clicking on the button will invoke add () method to generate a random number on the chart.

Step 1: Setup the project

ng new highChart
cd highChart

npm i --save angular-highcharts highcharts
npm i --save-dev @types/highcharts

Step 2: Create a component SimplechartComponent 

ng generate component simplechart

Add the following code in SimplechartComponent.ts

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

@Component({
  selector: 'app-simplechart',
  templateUrl: './simplechart.component.html',
  styleUrls: ['./simplechart.component.css']
})
export class SimplechartComponent implements OnInit {

  chart = new Chart({
    chart: {
      type: 'line'
    },
    title: {
      text: 'Linechart'
    },
    credits: {
      enabled: false
    },
    series: [{
      name: 'Line 1',
      data: [10, 20, 30, 50, 15, 30, 60,80]
    }]
  });

  constructor() { }

  ngOnInit() {
  }

  add() {
    this.chart.addPoint(Math.floor(Math.random() * 10));
  }
}

ྭWe have to import Chart from Angular-highcharts module in simplechartComponent.ts file and add the following code in simplechartComponent.html file

<button (click)="add()">Add Point!</button>
<div [chart]="chart"></div>

 

Step 3:  Use app-simplechart selector in app.component.html file

<div style="text-align:center">
  <h1>Welcome to {{title}}!</h1>
  <app-simplechart></app-simplechart>
</div>
<h2>Here Simple example of HighChart in Angular </h2>

Atlast we have to register or import the highChar module in app.module.ts file.


import { AppComponent } from './app.component';
import { ChartModule } from 'angular-highcharts';
import { SimplechartComponent } from './components/simplechart/simplechart.component';

@NgModule({
  declarations: [
    AppComponent,
    SimplechartComponent
  ],
  imports: [
    BrowserModule,
    ChartModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

 

Integrating Angular on Node Js

We’ll need to use the TypeScript transpiler to convert our TypeScript files into valid ES5 or ES6 JavaScript files.
Furthermore, since Angular is a front end framework, installing it requires the inclusion of JavaScript files in server or node application.  This can be done in various ways and the easiest one, run ng build and copy the code of dist folder of angular and store them in the public folder.

First, install all the dependency.

We are using mongojs, which provide easy and familiar syntax.

Configure the way we want the TypeScript compiler to run

In order to configure the way TypeScript works, we’ll need to add a new file called tsconfig.json to our application’s root folder. In your new file, paste the following JSON:

{
	"compilerOptions": {
		"target": "es6",
		"module": "system",
		"moduleResolution": "node",
		"sourceMap": true,
		"emitDecoratorMetadata": true,
		"experimentalDecorators": true,
		"removeComments": false,
		"noImplicitAny": false
	},
	"exclude": [
		"node_modules",
		"typings/main",
		"typings/main.d.ts"
	]
}

This file is the root of node folder. When we run our application, the TypeScript will use the tsconfig.json configuration file by default. Next, you’ll need to add a new file called typings.json to your application’s root folder. In your new file, paste the following JSON:


 

Step 1: Creating the backend server. First, we need to create Node backend.

mkdir clientKeeper
npm init 
//Fill all the requirement and set server.js
npm install express body-parser mongojs --save

Now we will create our server.js code as 

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');

const app = express();

const port = 3000;

//define db through mongojs

const mongojs = require('mongojs');
const db = mongojs('clientkeeper', ['clients']);

//set Static Folder
app.use(express.static(path.join(__dirname, 'public'))) ;
app.use(bodyParser.json());

app.get('/', (req, res) => {
    res.send('Please use /api/client');
});

app.listen(port, () => {
    console.log('Server start on port' +port);
});

Note in package.json we have to add  “start”: “node server” and we need to run our apps like >> npm start

 

Step 2: Handling Backend

Here we are developing backend, RESTFUL API with complete CRUD functionality.  We will now add code for routing and database. In server.js file add following code for routing before app.listen

//Get Clients - GET request
app.get('/api/clients', (req, res, next) => {
    db.clients.find().sort({first_name:1}, (err, clients) => {
        if(err){
            res.send(err);
        }
        res.json(clients);
    });
});

//Add Client - POST
app.post('/api/clients', (req, res, next) => {
    db.clients.insert(req.body, (err, client) => {
        if(err){
            res.send(err);
        }
        res.json(client);
    });
});

//Update Client - POST
app.put('/api/clients/:id', (req, res, next) => {
    const id = req.params.id;
    db.clients.findAndModify({query: {_id: mongojs.ObjectId(id)},
        update: {
            $set: {
                first_name: req.body.first_name,
                last_name: req.body.last_name,
                email : req.body.email,
                phone: req.body.phone
            }
        },
        new: true
    },(err, client) => {
        res.json(client);    
    });
});

//Add Client - DELETE
app.delete('/api/clients/:id', (req, res, next) => {
    const id = req.params.id;
    db.clients.remove({ _id: mongojs.ObjectId(id)}, (err, client) => {
        if(err){
            res.send(err);
        }
        res.json(client);
    });
});

app.listen(port, () => {
    console.log('Server start on port' +port);
});

Till now we didn’t set up the database, we can test the above code using chrome extension called RestEasy, we can make GET, POST, PUT and DELETE request. For requesting post we have to set header Content-type : application/json.


As what every we type in Rest Easy chrome extension will be inserted in the database, as we are posting data on behaving from the server by our chrome extension.

Step 3: Handling FrontEnd through Angular

We have to install angular cli as npm install -g angular-cli

We will create a project folder and put both node project clienttkeeper and angular project both inside the project folder.  In project folder in command line run following command.

>>ng new ckfrontend
>>cd ckfrontend
>>ng serve
By default angular run on port 4200

Once frontend is complete we will run ng build 
copy dist folder of angular to our public folder of backend.

Inside the app folder in Angular frontend we will create a folder called components in the app folder. Inside the components, folder creates new folder clients. Inside the clients, folder add two more file clients.component.ts and clients.component.html. Add the following code in clients.component.ts file

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

@Component({
  selector: 'clients',
  templateUrl: './clients.component.html'
})
export class ClientsComponent {}

and inside the clients.component.html add the following code.

Hello Clients

We need to declare the clients.component.ts file inside the app.module.ts

Step 4: Creating a Service in FrontEnd to access/fetch data from Backend

Now we will create services file, which will help us to make request to the backend database for the list of clients and will display the client’s information in clients.component.html. Create services folder and add a new file called clients.service.ts. Add the following code in app/services/clients.service.ts . 

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

@Injectable()
export class ClientService {
    constructor(private http: Http) {}

    getClients() {
        return this.http.get('http://localhost:3000/api/clients')
            .map(res => res.json());
    }
}

We are using HTTP to access the client data, we need to declare HttpModule and ClientService both in app.module.ts.

....
import { HttpModule } from '@angular/http';
......
import { ClientsComponent } from './components/clients/clients.component';
import { ClientService } from './services/clients.service';

@NgModule({
  declarations: [
    AppComponent,
    ClientsComponent
  ],
  imports: [
    BrowserModule,
    HttpModule
  ],
  providers: [ ClientService ],
  bootstrap: [AppComponent]
})
export class AppModule { }

 

In clients.component.ts we are using ClientService so we have to import service in clients.component.ts file.

Add the following code in app/components/clients.component.ts

import { Component, OnInit } from '@angular/core';
import { ClientService } from '../../services/clients.service';

@Component({
  selector: 'clients',
  templateUrl: './clients.component.html'
})

export class ClientsComponent implements OnInit {
  constructor(private clientService: ClientService) {
  }

  ngOnInit() {
    this.clientService.getClients().subscribe(clients => {
      console.log(clients);
    });
  }
}

Note:

  1. We want to run getClients method from ClientService immediately, we can put in the constructor but best and recommended way to do it is used lifecycle method called OnInit. We have to import it in our clients.component.ts file and implement it in our class as in code and ngOnInit() will run immediately with the clients.component.ts class.  Add the following code in app/components/clients.component.ts
  2. this.clientService.getClients().subscribe(clients=> { – the getClients will return Observable, we have to catch it through subscribing , it will give as data.
  3. We have to run both front and back end in command mode. Port 3000 for node and 4200 for angular. On access the client code on browser http://localhost:4200/ we get the error message.

We are getting an error because we request from the different domain, so we have to add middleware in backend or node to allow access from localhost:4200 and add the following code in backend server.js file.

//Allow request from Angular
app.use((req, res, next) => {
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
    //Request methods u wish to allow
    
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    //Request header you widht to allow
    
res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
    //Pass to next Layer of middleware
   
 next();
})

 

Step 5: Displaying the client list in the template.

We above code, the client will access the data from the backend and display the client information through console.log. Now instead of log to console, we will assign the client data to a variable in component the clients.component.ts file and we can access with the template and display the client in clients.component.html file.

We will modify the clients.component.ts file from log to

export class ClientsComponent implements OnInit {
  clients;
  
  constructor(private clientService: ClientService) {
  }

  ngOnInit() {
    this.clientService.getClients().subscribe(clients => {
      this.clients = clients;
    });
  }
}

Once we assign the client to local variable we can easily access  in template and can loop client data through ngFor. Add the following code in app/components/clients.component.html

<div class="client-list">
    <table class="table table-striped">
        <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Email</th>
            <th>Phone</th>
            <th></th>
        </tr>
        <tr *ngFor="let client of clients">
            <td>{{clients.first_name}}</td>
            <td>{{clients.last_name}}</td>
            <td>{{clients.email}}</td>
            <td>{{clients.phone}}</td>
            <td><a href="" class="btn btn-default">Edit</a>
 <a href="" class="btn btn-danger">Delete</a></td>
        </tr>
    </table>
</div>

As till now we didn’t apply any style, we can use bootswatch theme spacelab and insert bootstrap link in client index.html as

........
  <base href="/">

  <link rel="stylesheet" href="https://bootswatch.com/spacelab/bootstrap.min.css">
  <meta name="viewport" content="width=device-width, initial-scale=1">
.....

 

In a client or angular side, we create a new component called navbar. Create a folder navbar in app/components and add two file as navbar.component.ts and navbar.component.html file. Inside the navbar.component.ts file add the following code

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

@Component({
  selector: 'navbar',
  templateUrl: './navbar.component.html'
})

export class NavbarComponent {
  constructor() {}
}

 

Add the following line of code in navbar.component.html file

<nav class="navbar navbar-inverse">
    <div class="container">
        <div class="navbar-header">
            <a class="navbar-brand" href="/">ClientKeeper</a>
        </div>
    </div>
</nav>

We also have to import our new navbarcomponent in app.module.ts file. Inside the app/app.component.html file add our new navbar tag.

<navbar></navbar>
<div class="container">
    <clients></clients>
</div>

On accessing the client or angular on browser we will get 

 

 Step 6: Adding new Client information from the front end to back end. 

We will create a form in angular, so we can insert new client from angular to the node. In app/components/clients/client.component.html add the following code for form for adding new client.

<div class="client-form">
    <form (submit)="onAddSubmit()" class="well">
        <h3>Add Client</h3>
        <div class="form-group">
            <label>First Name</label>
            <input type="text" class="form-control" [(ngModel)]="first_name" name="first_name" placeholder="First Name">
        </div>
        <div class="form-group">
            <label>Last Name</label>
            <input type="text" class="form-control" [(ngModel)]="last_name" name="last_name" placeholder="Last Name">
        </div>
        <div class="form-group">
            <label>Email</label>
            <input type="text" class="form-control" [(ngModel)]="email" name="email" placeholder="Email">
        </div>
        <div class="form-group">
            <label>Phone Number</label>
            <input type="text" class="form-control" [(ngModel)]="phone" name="phone" placeholder="Phone Number">
        </div>
        <button type="submit" class="btn btn-primary">Submit</button>
    </form>
</div>
<div class="client-list">
    <table class="table table-striped">
        <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Email</th>
            <th>Phone</th>
            <th></th>
        </tr>
        <tr *ngFor="let client of clients">
            <td>{{client.first_name}}</td>
            <td>{{client.last_name}}</td>
            <td>{{client.email}}</td>
            <td>{{client.phone}}</td>
            <td><a href="" class="btn btn-default">Edit</a> <a href="" class="btn btn-danger">Delete</a></td>
        </tr>
    </table>
</div>

We have onAddSubmit() on form, this function is called when we click on submit button and we have to define definition for the onAddSubmit() function. Add the following code in app/components/clients/client.component.ts

export class ClientsComponent implements OnInit {
  clients;
    _id;
  first_name;
  last_name;
  email;
  phone;

  constructor(private clientService: ClientService) {
  }

  ngOnInit() {
	...
  }

   onAddSubmit() {
    let newClient = {
      first_name: this.first_name,
      last_name: this.last_name,
      email: this.email,
      phone: this.phone
    }

    this.clientService.saveClient(newClient).subscribe(client => {
     this.clients.push(client);
     this.first_name = '';
     this.last_name = '';
     this.email = '';
     this.phone = '';
   });
   }
}

Note:

  1. We have to define FormModule in app.module.ts and no need to import form module in client.component.ts
  2. We will create new client object in onAddSubmit() {…}
  3. Inside onAddSubmit(){ … we have this.clientService.saveClient(newClient).subscribe(client => { … here we are sending our new client to clientService in app/service folder. Where we will insert new user from client or angular to database in backend.

We need to add saveClient(newClient) method in services/client.service.ts at the end of file

    saveClient(client){
        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        return this.http.post('http://localhost:3000/api/clients', client, {headers: headers})
            .map(res => res.json());
    }

We can insert new client from the front end as in screen shot

Step 7: Adding the edit functionality in FrontEnd

Now we will add edit functionality in client apps. We will create the separate form for adding and editing. We need a way to tell the apps when to use add and edit form.  That can be achieved through setting are a variable called isEdit in our client.component.ts file.  By default set isEdit to false. Add the following code in app/components/clients/clients.component.ts file.

import { Component, OnInit } from '@angular/core';
import {ClientService} from '../../services/client.service';

@Component({
  selector: 'clients',
  templateUrl: './clients.component.html'
})
export class ClientsComponent implements OnInit{
  clients;
  _id;
  first_name;
  last_name;
  email;
  phone;
  isEdit;
  constructor(private clientService: ClientService){
  
  }

 ngOnInit(){
   this.clientService.getClients().subscribe(clients => {
     this.clients = clients;
   });

   this.isEdit = false;
 }

 onAddSubmit(){
   let newClient = {
   ....
 }

 onEditSubmit(){
   let updClient = {
     first_name: this.first_name,
     last_name: this.last_name,
     email: this.email,
     phone: this.phone,
     _id: this._id
   }

   this.clientService.updateClient(updClient).subscribe(client => {
     for(let i = 0; i < this.clients.length;i++){
       if(client._id == this.clients[i]._id){
         this.clients.splice(i, 1);
       }
     }
     this.clients.push(client);
     this.first_name = '';
     this.last_name = '';
     this.email = '';
     this.phone = '';
   });
 }

 onEditClick(client){
   this.isEdit = true;
   this.first_name = client.first_name;
   this.last_name = client.last_name;
   this.email = client.email;
   this.phone = client.phone;
   this._id = client._id;
 }
}
  1. We will call onEditClick(client) method on clicking the edit button on client information in the page
  2. Will call on onEditSubmit() method on clicking on submit of edit form. 
  3. We have service function to update the client information as on this.clientService.updateClient(updClient).subscribe(client => we have to create corresponding function in ClientService. 

In app/components/clients/clients.components.html. We have two ngIf

<div *ngIf="isEdit">
and 
<div *ngIf="!isEdit">

The first ngIf will display the edit form only when isEdit variable value is true that can be set only by clicking on the edit button and the second ngIf will display add new client form as by default isEdit is false. Add the following code in app/components/clients/clients.component.htlm

<div class="client-form">
    <div *ngIf="isEdit">
        <form (submit)="onEditSubmit()" class="well">
            <h3>Edit Client</h3>
            <div class="form-group">
                <label>First Name</label>
                <input type="text" class="form-control" [(ngModel)]="first_name" name="first_name" placeholder="First Name">
            </div>
            <div class="form-group">
                <label>Last Name</label>
                <input type="text" class="form-control" [(ngModel)]="last_name" name="last_name" placeholder="Last Name">
            </div>
            <div class="form-group">
                <label>Email</label>
                <input type="text" class="form-control" [(ngModel)]="email" name="email" placeholder="Email">
            </div>
            <div class="form-group">
                <label>Phone Number</label>
                <input type="text" class="form-control" [(ngModel)]="phone" name="phone" placeholder="Phone Number">
            </div>
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
    </div>

    <div *ngIf="!isEdit">
        <form (submit)="onAddSubmit()" class="well">
            <h3>Add Client</h3>
            <div class="form-group">
                <label>First Name</label>
                <input type="text" class="form-control" [(ngModel)]="first_name" name="first_name" placeholder="First Name">
            </div>
            <div class="form-group">
                <label>Last Name</label>
                <input type="text" class="form-control" [(ngModel)]="last_name" name="last_name" placeholder="Last Name">
            </div>
            <div class="form-group">
                <label>Email</label>
                <input type="text" class="form-control" [(ngModel)]="email" name="email" placeholder="Email">
            </div>
            <div class="form-group">
                <label>Phone Number</label>
                <input type="text" class="form-control" [(ngModel)]="phone" name="phone" placeholder="Phone Number">
            </div>
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
    </div>
</div>
<div class="client-list">
    <table class="table table-striped">
        <tr>
            <th>First Name</th>
        ...
        </tr>
        <tr *ngFor="let client of clients">
            <td>{{client.first_name}}</td>
     ...
            <td>{{client.phone}}</td>
            <td><a (click)="onEditClick(client)" href="#" class="btn btn-default">Edit</a> <a href="" class="btn btn-danger">Delete</a></td>
        </tr>
    </table>
</div>

In template, we are creating click event (click)=onEditClick(client) on anchor edit button.

In app/services/client.service.ts we will add the corresponding code of edit form. Add the following code client.service.ts

    updateClient(client){
        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        return this.http.put('http://localhost:3000/api/clients/'+client._id, client, {headers: headers})
            .map(res => res.json());
    }

Step 8: Adding Delete functionality in the front end.

In app/components/clients/clients.component.html add the following code for delete.

<div class="client-form">
    <div *ngIf="isEdit">
        <form (submit)="onEditSubmit()" class="well">
            <h3>Edit Client</h3>
        ....
    </div>

    <div *ngIf="!isEdit">
        <form (submit)="onAddSubmit()" class="well">
            <h3>Add Client</h3>
        .....
    </div>
</div>
<div class="client-list">
    <table class="table table-striped">
        <tr>
            <th>First Name</th>
...
            <th></th>
        </tr>
        <tr *ngFor="let client of clients">
            <td>{{client.first_name}}</td>
 ...
            <td>{{client.phone}}</td>
            <td><a (click)="onEditClick(client)" href="#" class="btn btn-default">Edit</a> 
            <a (click)="onDeleteClick(client._id)" href="#" class="btn btn-danger">Delete</a></td>
        </tr>
    </table>
</div>

We have add method definition for <a (click)=”onDeleteClick(client._id) in app/components/cleints/clients.component.ts file.

  onDeleteClick(id) {
   this.clientService.deleteClient(id).subscribe(client => {
      for(let i = 0; i < this.clients.length;i++){
        if(id == this.clients[i]._id){
          this.clients.splice(i, 1);
        }
      }
    });
  }

In app/services/client.service.ts we will add the corresponding code of delete. Add the following code client.service.ts

    deleteClient(id){
        return this.http.delete('http://localhost:3000/api/clients/'+id)
            .map(res => res.json());
    }

 

Important: We have complete all the front end code, now we add our angular code in Node. For that, we have run following command at angular cli
>>ng build
The command will build our front end application in dist folder, which we will copy and past in public folder of server or node js. Now run the node server as

>>npm start 

We can use our angular in node server as screen shot.


NOW WE HAVE COMPLETE INTEGRATE FROM ANGULAR TO NODE

As above code are the chunk of the different file, now we will add combine all code in its corresponding file.
Adding all the server code
In Node we have server.js file in root add all it code as

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');

const app = express();

const port = 3000;

//define db through mongojs

const mongojs = require('mongojs');
const db = mongojs('clientkeeper', ['clients']);

//set Static Folder
app.use(express.static(path.join(__dirname, 'public'))) ;
app.use(bodyParser.json());

//Allow request from Angular
app.use((req, res, next) => {
    res.setHeader('Access-Control-Allow-Origin', 'http://localhost:4200');
    //Request methods u wish to allow
    res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE');
    //Request header you widht to allow
    res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With, Content-Type');
    //Pass to next Layer of middleware
    next();
    
})



app.get('/', (req, res) => {
    res.send('Please use /api/client');
});

//Get Clients - GET request
app.get('/api/clients', (req, res, next) => {
    db.clients.find().sort({first_name:1}, (err, clients) => {
        if(err){
            res.send(err);
        }
        res.json(clients);
    });
});

//Add Client - POST
app.post('/api/clients', (req, res, next) => {
    db.clients.insert(req.body, (err, client) => {
        if(err){
            res.send(err);
        }
        res.json(client);
    });
});

//Update Client - POST
app.put('/api/clients/:id', (req, res, next) => {
    const id = req.params.id;
    db.clients.findAndModify({query: {_id: mongojs.ObjectId(id)},
        update: {
            $set: {
                first_name: req.body.first_name,
                last_name: req.body.last_name,
                email : req.body.email,
                phone: req.body.phone
            }
        },
        new: true
    },(err, client) => {
        res.json(client);    
    });
});

//Add Client - DELETE
app.delete('/api/clients/:id', (req, res, next) => {
    const id = req.params.id;
    db.clients.remove({ _id: mongojs.ObjectId(id)}, (err, client) => {
        if(err){
            res.send(err);
        }
        res.json(client);
    });
});

app.listen(port, () => {
    console.log('Server start on port' +port);
});

 

Adding all the Client code

First we will add all the code on client component, add the complete code of app/components/clients/clients.component.ts file

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

@Injectable()
export class ClientService{
    constructor(private http: Http){

    }

    getClients(){
        return this.http.get('http://localhost:3000/api/clients')
            .map(res => res.json());
    }

    saveClient(client){
        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        return this.http.post('http://localhost:3000/api/clients', client, {headers: headers})
            .map(res => res.json());
    }

    updateClient(client){
        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        return this.http.put('http://localhost:3000/api/clients/'+client._id, client, {headers: headers})
            .map(res => res.json());
    }
    
    deleteClient(id){
        return this.http.delete('http://localhost:3000/api/clients/'+id)
            .map(res => res.json());
    }
        
}

Now we will add the complete code of app/components/clients/clients.component.html file

<div class="client-form">
    <div *ngIf="isEdit">
        <form (submit)="onEditSubmit()" class="well">
            <h3>Edit Client</h3>
            <div class="form-group">
                <label>First Name</label>
                <input type="text" class="form-control" [(ngModel)]="first_name" name="first_name" placeholder="First Name">
            </div>
            <div class="form-group">
                <label>Last Name</label>
                <input type="text" class="form-control" [(ngModel)]="last_name" name="last_name" placeholder="Last Name">
            </div>
            <div class="form-group">
                <label>Email</label>
                <input type="text" class="form-control" [(ngModel)]="email" name="email" placeholder="Email">
            </div>
            <div class="form-group">
                <label>Phone Number</label>
                <input type="text" class="form-control" [(ngModel)]="phone" name="phone" placeholder="Phone Number">
            </div>
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
    </div>

    <div *ngIf="!isEdit">
        <form (submit)="onAddSubmit()" class="well">
            <h3>Add Client</h3>
            <div class="form-group">
                <label>First Name</label>
                <input type="text" class="form-control" [(ngModel)]="first_name" name="first_name" placeholder="First Name">
            </div>
            <div class="form-group">
                <label>Last Name</label>
                <input type="text" class="form-control" [(ngModel)]="last_name" name="last_name" placeholder="Last Name">
            </div>
            <div class="form-group">
                <label>Email</label>
                <input type="text" class="form-control" [(ngModel)]="email" name="email" placeholder="Email">
            </div>
            <div class="form-group">
                <label>Phone Number</label>
                <input type="text" class="form-control" [(ngModel)]="phone" name="phone" placeholder="Phone Number">
            </div>
            <button type="submit" class="btn btn-primary">Submit</button>
        </form>
    </div>
</div>
<div class="client-list">
    <table class="table table-striped">
        <tr>
            <th>First Name</th>
            <th>Last Name</th>
            <th>Email</th>
            <th>Phone</th>
            <th></th>
        </tr>
        <tr *ngFor="let client of clients">
            <td>{{client.first_name}}</td>
            <td>{{client.last_name}}</td>
            <td>{{client.email}}</td>
            <td>{{client.phone}}</td>
            <td><a (click)="onEditClick(client)" href="#" class="btn btn-default">Edit</a> 
            <a (click)="onDeleteClick(client._id)" href="#" class="btn btn-danger">Delete</a></td>
        </tr>
    </table>
</div>

As app/components/navbar and app/app.component.html we are not adding any data as it already added the complete data.

We have to add complete code for app/services/client.service.ts

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

@Injectable()
export class ClientService{
    constructor(private http: Http){

    }

    getClients(){
        return this.http.get('http://localhost:3000/api/clients')
            .map(res => res.json());
    }

    saveClient(client){
        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        return this.http.post('http://localhost:3000/api/clients', client, {headers: headers})
            .map(res => res.json());
    }

    updateClient(client){
        let headers = new Headers();
        headers.append('Content-Type', 'application/json');
        return this.http.put('http://localhost:3000/api/clients/'+client._id, client, {headers: headers})
            .map(res => res.json());
    }
    
    deleteClient(id){
        return this.http.delete('http://localhost:3000/api/clients/'+id)
            .map(res => res.json());
    }
        
}

Angular – Github

We are building Github profile finder, in our app, we have a search bar and based on the name we supply. App will search following information on that particular user

  1. User profile information and avatar
  2. Follower info
  3. Github repository info

Important: As  from Angular point, we are learning ngIf to control the display, at first we set user to false, as this result our page is blank with only search bar and once we type any character it will set user to that character and find information on that user , as we can see on image above.

What we are learning

  1. Retrieving Github API through HTTP get method .
  2. Making service provider
  3. Importing form module for searching information through form

 

Step 1: Getting Github Client Id
To use the Github API, we need to get a client id and client secret, that we will get from github.com/settgins/developer and register for a new application.

Step 2: Setting the App in Angular
ng new githubse
npm install (install the dependency)
npm start
Check on browser on url localhost:4200

Step 3: Creating Profile component

Create a folder components inside the app folder and add new two new files as profile.component.ts and profile.component.html. Inside the profile.component.ts add the following code [app/components/profile.component.ts]

import { Component } from '@angular/core';
import {GithubService} from '../services/github.service';

@Component({
  moduleId: module.id,
  selector: 'profile',
  templateUrl: 'profile.component.html',
})

export class ProfileComponent { 
    user:any;
    repos:any[];
    username: string;
    
    constructor(private _githubService: GithubService){
        this.user = false;
    }

    searchUser(){
        this._githubService.updateUser(this.username);

        this._githubService.getUser().subscribe(user => {
            this.user = user;
        });

        this._githubService.getRepos().subscribe( repos => {
            this.repos = repos;
        });

    }
}

We are importing the GithubService service provider and calling its method through the instance of GithubService and subscribing the observable which we will define in step 5. What we are doing.

  1. Calling Github user information through GithubService method getUser()
  2. Retrieving user repository through getRepos()
  3. Search different user through updating or change new username through updateUser() of GithubService

Step 4: Add the view for profile.component.html, add the following code in [app/components/profile.component.html]. In this code, we add a search bar to retrieve Github user information like profile, avatar, followers and repository details information.

<div class="row">
    <div class="col-md-12">
        <form class="well"> 
            <div class="form-group">
                <input type="text" class="form-control" placeholder="Enter Github Username .." [(ngModel)]="username" name="username" (keyup)="searchUser()">
            </div>
        </form>
    </div>    
</div> <!-- End of row -->

<div *ngIf="user">
   <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">{{user.name}}</h3>
        </div>
        <div class="panel-body">
            <div class="row">
                <div class="col-md-4">
                    <img class="img-thumbnail" src="{{user.avatar_url}}">
                    <a class="btn btn-default btn-block" target="_blank" href="{{user.html_url}}">View Profile</a>
                </div>
                <div class="col-md-8">
                    <div class="stats">
                        <span class="label label-default">{{user.public_repos}} Public Repos</span>
                        <span class="label label-primary">{{user.public_gists}} Public Gists</span>
                        <span class="label label-success">{{user.followers}} Followers</span>
                        <span class="label label-info">{{user.following}} Following</span>
                    </div>
                    <br>
                    <ul class="list-group">
                        <li class="list-group-item"><strong>Username: </strong>{{user.login}}</li>
                        <li class="list-group-item"><strong>Location: </strong>{{user.location}}</li> 
                        <li class="list-group-item"><strong>Email: </strong>{{user.email}}</li> 
                        <li class="list-group-item"><strong>Blog: </strong>{{user.blog}}</li> 
                        <li class="list-group-item"><strong>Member Since: </strong>{{user.created_at}}</li> 
                    </ul>
                </div>    
            </div>
        </div>
    </div>
    
    <div class="panel panel-default">
        <div class="panel-heading">
            <h3 class="panel-title">User Repos</h3>
        </div>
        <div class="panel-body">
            <div *ngFor="let repo of repos">
                  <div class="row">
                    <div class="col-md-9">
                        <h4><a target="_blank" href="{{repo.html_url}}">{{repo.name}}</a></h4>
                        <p>{{repo.description}}</p>
                    </div>
                    <div class="col-md-3">
                        <span class="label label-default">{{repo.watchers}} Watchers</span>
                        <span class="label label-primary">{{repo.forks}} Forks</span>
                    </div>  
                  </div>
                  <hr>
            </div>
        </div>
    </div>
</div>

 

In app/app.component.ts we will replace following code

@Component({
	.......
	template: '<h1>My First Angular App</h1>
})

To new code, where we add our custom tag profile and wrap in container div and add nav bar code from bootstrap starter code and add the provider as in highlight in the code

import { Component } from '@angular/core';
import { GithubService } from './services/github.service';

@Component({
  selector: 'app-root',
  template: `
     <nav class="navbar navbar-default">
      <div class="container">
        <div class="navbar-header">
          <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
            <span class="sr-only">Toggle navigation</span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
            <span class="icon-bar"></span>
          </button>
          <a class="navbar-brand" href="#">Github Search</a>
        </div>
        <div id="navbar" class="collapse navbar-collapse">
          <ul class="nav navbar-nav">
           
          </ul>
        </div><!--/.nav-collapse -->
      </div>
    </nav>
    <div class="container">
        <profile></profile>
    </div>`,
        
  styleUrls: ['./app.component.css'],
  providers: [ GithubService ]
})
export class AppComponent {
  title = 'app';
}

 

Step 5: Creating  Service for Github API
We will create Github services so that it can interact with Github API. In the app, folder creates a folder called services, inside this folder add a new file called app/services/github.service.ts. Add the following code

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

@Injectable()
export class GithubService{
    private username:string;
    private client_id ='386c70968833e0b2c';
    private client_secret = '4af330c6ca939274cee0a5221a8469edd3e';

    constructor(private _http: Http){
        console.log('Github Service Ready...');
        this.username = 'n????p';
    }

    getUser(){
        return this._http
        .get('http://api.github.com/users/' + this.username + '?client_id=' + this.client_id + '&client_secret=' + this.client_secret)
            .map(res => res.json());
    }

    getRepos(){
        return this._http
        .get('http://api.github.com/users/' + this.username + '/repos?client_id=' + this.client_id + '&client_secret=' + this.client_secret)
            .map(res => res.json());
    }

    updateUser(username:string){
        this.username = username;
    }
}

In above code,

  1. we are retrieving user information in JSON format through HTTP module and we have to supply client ID and secret key.
  2. Import injectable so we can create dependency on service into whatever component we need.
  3. Import rxjs, observable with the reactive extension will return the response to observable, then we can subscribe to the observable component to display the information.

Step 6: Define user interface through Bootstrap
Add the following link in src/index.html, this is not best practices.

<!doctype html>
<html lang="en">
<head>
.........

  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">

 

In app.modules.ts, we have to define imported module, the custom component which we had used in our application.

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

import { ProfileComponent } from './components/profile.component';

@NgModule({
  declarations: [ AppComponent, ProfileComponent],
  imports: [ BrowserModule, HttpModule, FormsModule ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }