Sunday 10 December 2017

Angular 4

Node -v
Check npm version in your system
Npm -v
Check npm version in your system
Npm install -g @angular/cli
Install angular cli
Ng -v
See angular install status
Ng new nameofproject
Create angular 4 project
Npm install
Install npm packages
Ng serve
Compile angular 4 application
ng g component my-component
To add new componet
ng g service servicename
To create service
npm install @angular/animations@latest --save
To install animation package
npm install bootstrap@4.0.0-beta.2
Install boot strap
Npm g pipe pipename
To add new pipe
Code .
Open in visual code
Ng build
Build project
Ng build --prod

ng g m products/product --flat -m app.module




"bootstrap": "^3.3.7",
    "core-js": "^2.4.1",
    "rxjs": "^5.4.2",
    "zone.js": "^0.8.14"

 "styles": [
        "styles.css",
        "../node_modules/bootstrap/dist/css/bootstrap.css"
      ],

Index.html

<!doctype html>
<html lang="en">
<head>
  <meta charset="utf-8">
  <title>Acme Product Management</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
  <pm-root></pm-root>
</body>
</html>


products.json

[
    {
        "productId": 1,
        "productName": "Leaf Rake",
        "productCode": "GDN-0011",
        "releaseDate": "March 19, 2016",
        "description": "Leaf rake with 48-inch wooden handle.",
        "price": 19.95,
        "starRating": 3.2,
        "imageUrl": "http://openclipart.org/image/300px/svg_to_png/26215/Anonymous_Leaf_Rake.png"
    }
]

app.module.ts

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { HttpClientModule } from '@angular/common/http'
import { RouterModule } from '@angular/router'


import { AppComponent } from './app.component';
import { ProductListComponent } from './products/product-list.component';
import { ConvertToSpacesPipe } from './shared/convert-to-spaces.pipe';
import { StarComponent } from './star/star.component';
import { ProductDetailsComponent } from './products/product-details/product-details.component';
import { HomeComponent } from './home/home/home.component';
import { ProductGuardService } from "./products/product-guard.service";

@NgModule({
  declarations: [
    AppComponent,
    ProductListComponent,
    ConvertToSpacesPipe,
    StarComponent,
    ProductDetailsComponent,
    HomeComponent
  ],
  imports: [
    BrowserModule,
    FormsModule,
    HttpClientModule,
    RouterModule.forRoot([
      { path: 'products', component: ProductListComponent },
      { path: 'products/:id', canActivate: [ProductGuardService], component: ProductDetailsComponent },
      { path: 'welcome', component: HomeComponent },
      { path: '', redirectTo: 'welcome', pathMatch: 'full' },
      { path: '**', redirectTo: 'welcome', pathMatch: 'full' },
    ])
  ],
  providers: [ProductGuardService],
  bootstrap: [AppComponent,]
})
export class AppModule { }

app.component.ts

import { Component } from '@angular/core';
import { ProductService } from "./products/product.service";

@Component({
  selector: 'pm-root',
  template: `<div>
  <nav class='navbar navbar-default'>
      <div class='container-fluid'>
          <a class='navbar-brand'>{{pageTitle}}</a>
          <ul class='nav navbar-nav'>
              <li><a [routerLink]="['/welcome']">Home</a></li>
              <li><a [routerLink]="['/products']">Product List</a></li>
          </ul>
      </div>
  </nav>
  <div class='container'>
      <router-outlet></router-outlet>
  </div>
</div>`,
  providers: [ProductService]
})
export class AppComponent {
  pageTitle: string = 'Acme ProductManagement';
}

Products

product.ts

export interface IProduct {
    productId: number,
    productName: string,
    productCode: string,
    releaseDate: string,
    description: string,
    price: number,
    starRating: number,
    imageUrl: string;
}

product.service.ts

import { Injectable } from '@angular/core';
import { HttpClient, HttpErrorResponse } from "@angular/common/http";
import { Observable } from "rxjs/Observable";
import "rxjs/add/observable/throw";
import "rxjs/add/operator/catch";
import "rxjs/add/operator/do";
import 'rxjs/add/operator/map';
import { IProduct } from "./product";


@Injectable()
export class ProductService {
  constructor(private _http: HttpClient) { }

  private _productUrl = '../assets/products/products.json';
  getProducts(): Observable<IProduct[]> {
    return this._http.get<IProduct[]>(this._productUrl)
      .do(data => console.log("All: " + JSON.stringify(data)))
      .catch(this.handleError);
  }
  getProduct(id: number): Observable<IProduct> {
    return this.getProducts()
      .map((products: IProduct[]) => products.find(p => p.productId === id));
  }
  private handleError(err: HttpErrorResponse) {
    console.log(err.message);
    return Observable.throw(err.message);
  }
}


product-list.component.ts

import { Component, OnInit } from '@angular/core';
import { IProduct } from "./product";
import { ProductService } from "../products/product.service";


@Component({
  templateUrl: './product-list.component.html',
  styleUrls: ['./product-list.component.css']
})
export class ProductListComponent implements OnInit {
  pageTitle: string = 'Product List';
  imageWidth: number = 50;
  imageMargin: number = 2;
  showImage: boolean = false;
  _listFilter: string;
  errorMessage: string;

  get listFilter(): string {
    return this._listFilter;
  }

  set listFilter(value: string) {
    this._listFilter = value;
    this.filterProducts = this.listFilter ? this.performFilter(value) : this.products;
  }

  filterProducts: IProduct[];
  products: IProduct[] = [];

  constructor(private _productService: ProductService) {
  }
  toggleImage(): void {
    this.showImage = !this.showImage;
  }

  ngOnInit(): void {
    this._productService.getProducts()
      .subscribe(products => {
        this.products = products;
        this.filterProducts = this.products;
      },
      error => this.errorMessage = <any>error);

  }

  performFilter(filterBy: string): IProduct[] {
    filterBy = filterBy.toLocaleLowerCase();
    return this.products.filter((product: IProduct) =>
      product.productName.toLocaleLowerCase().indexOf(filterBy) !== -1);
  }

  onRatingClicked(message: string): void {
    this.pageTitle = 'Product List:' + message;
  }
}

product-list.component.html

<div class='panel panel-primary'>
    <div class='panel-heading'>
        {{pageTitle}}
    </div>
    <div class='panel-body'>
        <div class='row'>
            <div class='col-md-2'>Filter by:</div>
            <div class='col-md-4'>
                <input type='text' [(ngModel)]='listFilter' />
            </div>
        </div>
        <div class='row'>
            <div class='col-md-6'>
                <h3>Filtered by:{{listFilter}}</h3>
            </div>
        </div>
        <div class='table-responsive'>
            <table class='table' *ngIf='products && products.length'>
                <thead>
                    <tr>
                        <th>
                            <button class='btn btn-primary' (click)='toggleImage()'>
                           {{showImage?'Hide':'Show'}} Image
                          </button>
                        </th>
                        <th>Product</th>
                        <th>Code</th>
                        <th>Available</th>
                        <th>Price</th>
                        <th>5 Star Rating</th>
                    </tr>
                </thead>
                <tbody *ngFor='let product of filterProducts'>
                    <tr>
                        <td><img *ngIf='showImage' [src]='product.imageUrl' [title]='product.productName' [style.width.px]='imageWidth'
                                [style.margin.px]='imageMargin'> </td>
                        <td>
                            <a [routerLink]="['/products',product.productId]"> {{product.productName}}</a></td>
                        <td>{{product.productCode | lowercase | convertToSpaces:'-'}} </td>
                        <td>{{product.releaseDate}} </td>
                        <td>{{product.price | currency:'USD':true:'1.1-2'}} </td>
                        <td>
                            <pm-star [rating]='product.starRating' (ratingClicked)='onRatingClicked($event)'></pm-star>
                        </td>
                    </tr>
                </tbody>
            </table>
        </div>
    </div>
</div>
<div class='alert alert-danger'>
</div>

product-list.component.css

thead{
    color: blue
}

product-guard.service.ts

import { Injectable } from '@angular/core';
import { CanActivate, ActivatedRouteSnapshot, Router } from "@angular/router";

@Injectable()
export class ProductGuardService implements CanActivate {

  constructor(private _router: Router) { }

  canActivate(route: ActivatedRouteSnapshot): boolean {
    let id = +route.url[1].path;
    if (isNaN(id) || id < 1) {
      alert('Invalid product id');
      this._router.navigate(['/products']);
      return false;
    }
    return true;
  }

}

product-details


product-details.component.ts

import { Component, OnInit } from '@angular/core';
import { ActivatedRoute, Router } from '@angular/router';
import { IProduct } from "../product";
import { ProductService } from "../product.service";

@Component({
  templateUrl: './product-details.component.html',
  styleUrls: ['./product-details.component.css']
})
export class ProductDetailsComponent implements OnInit {
  pageTitle: string = 'Product Details';
  product: IProduct;
  errorMessage: string;

  constructor(private _route: ActivatedRoute, private _router: Router,
    private _productService: ProductService) { }

  ngOnInit() {
    let param = +this._route.snapshot.paramMap.get('id');
    if (param) {
      const id = +param;
      this.getProduct(id);
    }
  }

  getProduct(id: number) {
    this._productService.getProduct(id).subscribe(
      product => this.product = product,
      error => this.errorMessage = <any>error);
  }

  onBack(): void {
    this._router.navigate(['products/']);
  }

}

product-details.component.html

<div class='panel panel-primary' *ngIf='product'>
  <div class='panel-heading'>
    {{pageTitle + ': ' + product.productName}}
  </div>
  <div class='panel-body'>
    <div class='row'>
      <div class='col-md-6'>
        <div class='row'>
          <div class='col-md-3'>Name:</div>
          <div class='col-md-6'>{{product.productName}}</div>
        </div>
        <div class='row'>
          <div class='col-md-3'>Code:</div>
          <div class='col-md-6'>{{product.productCode | lowercase | convertToSpaces: '-'}}</div>
        </div>
        <div class='row'>
          <div class='col-md-3'>Description:</div>
          <div class='col-md-6'>{{product.description}}</div>
        </div>
        <div class='row'>
          <div class='col-md-3'>Availability:</div>
          <div class='col-md-6'>{{product.releaseDate}}</div>
        </div>
        <div class='row'>
          <div class='col-md-3'>Price:</div>
          <div class='col-md-6'>{{product.price|currency:'USD':true}}</div>
        </div>
        <div class='row'>
          <div class='col-md-3'>5 Star Rating:</div>
          <div class='col-md-6'>
            <pm-star [rating]='product.starRating'>
            </pm-star>
          </div>
        </div>
      </div>

      <div class='col-md-6'>
        <img class='center-block img-responsive' [style.width.px]='200' [style.margin.px]='2' [src]='product.imageUrl' [title]='product.productName'>
      </div>

    </div>
  </div>
  <div class='panel-footer'>
    <a class='btn btn-default' (click)='onBack()' style='width:80px'>
            <i class='glyphicon glyphicon-chevron-left'></i> Back
        </a>
  </div>
</div>

home


home.component.ts

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

@Component({
  templateUrl: './home.component.html'
})
export class HomeComponent implements OnInit {

  public pageTitle: string = 'Welcome';
  constructor() { }

  ngOnInit() {
  }

}

home.component.html

<div class="panel panel-primary">
  <div class="panel-heading">
    {{pageTitle}}
  </div>
  <div class="panel-body">
    <div class="row">
      <img src="./assets/images/logo.jpg" class="img-responsive center-block" style="max-height:300px;padding-bottom:50px" />
    </div>
    <div class="row">
      <div class="text-center">Developed by:</div>
      <h3 class="text-center">Deborah Kurata</h3>

      <div class="text-center">@deborahkurata</div>
      <div class="text-center">
        <a href="http://www.bit.ly/DeborahKsBlog">www.bit.ly/DeborahKsBlog</a>
      </div>
    </div>
  </div>
</div>

star


star.component.ts

import { Component, OnChanges, Input, Output, EventEmitter } from '@angular/core';

@Component({
  selector: 'pm-star',
  templateUrl: './star.component.html',
  styleUrls: ['./star.component.css']
})
export class StarComponent implements OnChanges {

  constructor() { }

  @Input() rating: number;
  starWidth: number;
  @Output() ratingClicked: EventEmitter<string> = new EventEmitter<string>();

  ngOnChanges(): void {
    this.starWidth = this.rating * 86 / 5;
  }

  onClick(): void {
    this.ratingClicked.emit(`The rating ${this.rating} was clicked`);
  }
}

star.component.html

<div class="crop" [style.width.px]="starWidth" [title]="rating" (click)="onClick()">
  <div style="width: 86px">
    <span class="glyphicon glyphicon-star"></span>
    <span class="glyphicon glyphicon-star"></span>
    <span class="glyphicon glyphicon-star"></span>
    <span class="glyphicon glyphicon-star"></span>
    <span class="glyphicon glyphicon-star"></span>
  </div>
</div>

shared


convert-to-spaces.pipe.ts


import { Pipe, PipeTransform } from "@angular/core";

@Pipe({
  name: 'convertToSpaces'
})

export class ConvertToSpacesPipe implements PipeTransform {
  transform(value: string, character: string): string {
    return value.replace(character, ' ');
  }
}