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, ' ');
}
}