<!DOCTYPE html>
<html>
<head>
<base href="." />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
<script type="text/javascript" charset="utf-8">
window.AngularVersionForThisPlunker = 'latest'
</script>
<title>angular playground</title>
<link rel="stylesheet" href="style.css" />
<script src="https://unpkg.com/core-js@2.4.1/client/shim.min.js"></script>
<script src="https://unpkg.com/zone.js/dist/zone.js"></script>
<script src="https://unpkg.com/zone.js/dist/long-stack-trace-zone.js"></script>
<script src="https://unpkg.com/reflect-metadata@0.1.3/Reflect.js"></script>
<script src="https://unpkg.com/systemjs@0.19.31/dist/system.js"></script>
<script src="config.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<script>
System.import('app')
.catch(console.error.bind(console));
</script>
</head>
<body>
<my-app>
loading...
</my-app>
</body>
</html>
//our root app component
import {Component, NgModule} from '@angular/core';
import {BrowserModule} from '@angular/platform-browser';
import {FormsModule} from '@angular/forms';
import {OrderComponent} from 'src/components/order/order';
import {ItemDetails} from 'src/components/item-details/item-details';
@Component({
selector: 'my-app',
template: `
<div>
<order></order>
</div>
`,
})
export class App {
constructor() {}
}
@NgModule({
imports: [ BrowserModule, FormsModule ],
declarations: [ App,OrderComponent,ItemDetails ],
bootstrap: [ App ]
})
export class AppModule {}
<div>
<div class="jumbotron-n">
<h3>Order Processing System</h3>
<div class="notification">
<div class="activeItem" *ngIf="order.status!=='Processed'">Currently processing Order # {{order.id}}</div>
<div class="success" *ngIf="order.status==='Processed'">Order Processed</div>
</div>
<div class="row">
<div class="col-xs-5 info-col">
<div class="col-xs-5 info-label">Order #</div>
<div class="col-xs-7 info-value">{{order.id}}</div>
</div>
<div class="col-xs-7 info-col">
<div class="col-xs-5 info-label">Order Date</div>
<div class="col-xs-7 info-value">{{order.date}}</div>
</div>
</div>
<div class="orderitems" style="padding-bottom:5px;">
<h5> Order Items</h5>
<ul class="list-group">
<li class="list-group-item"
[class.active]="item.status==='In Process'"
*ngFor="let item of order.items">
<span class="glyphicon glyphicon-ok" aria-hidden="true" *ngIf="item.status==='Processed'"></span>
<span class="badge">{{ item.quantity }}</span>
{{ item.name }}
</li>
</ul>
</div>
<div class="orderitems" style="padding-bottom:0">
<button type="button" class="btn btn-success" (click)="processNextOrCompleteOrder()">Start Processing Order Items</button>
</div>
</div>
<div class="itemDetailsContainer">
<item-details [item]="itemSelected" *ngIf="itemSelected"
[notifyItemProcessed]="processOrderItems" ></item-details>
</div>
</div>
import {Component, ChangeDetectorRef} from '@angular/core';
import {Orders} from 'src/data/orders';
import {ItemDetails} from 'src/components/item-details/item-details';
@Component({
selector: 'order',
templateUrl: 'src/components/order/order.html',
})
export class OrderComponent {
order: any;
itemSelected: any;
constructor(private cdRef:ChangeDetectorRef){
this.order = Orders[0];
}
onItemSelect(item){
this.itemSelected=item;
}
processNextOrCompleteOrder = () => {
let pendingItems = this.order.items.filter((item) => item.status === 'Not Processed' );
// get next item in the order
if (pendingItems.length > 0) {
this.itemSelected = pendingItems[0];
this.cdRef.detectChanges();
} else {
this.itemSelected = null;
this.cdRef.detectChanges();
this.completeOrder();
}
}
processOrderItems = () => {
this.itemSelected.status = "Processed";
this.processNextOrCompleteOrder();
}
completeOrder = () => this.order.status = "Processed";
}
//main entry point
import {platformBrowserDynamic} from '@angular/platform-browser-dynamic';
import {AppModule} from './app';
platformBrowserDynamic().bootstrapModule(AppModule);
export const Orders = [
{
id: 'A123',
date: '10/02/2017',
status: 'Not Processed',
customer:{
id: '010-28891',
name: 'Sunrise Group'
}
items: [
{
id: '001',
name: 'BetterHome Extra Soft Down Filled Pillow',
quantity: 2,
unitPrice: 6.12,
upc: 123456,
status: 'Not Processed'
},
{
id: '002',
name: 'Vaga Sportswear SPORT BAG',
quantity: 1,
unitPrice: 14.99,
upc: 123457,
status: 'Not Processed'
},
{
id: '003',
name: 'Rekor Quick Charge 3.0 39W Dual USB Wall Charger',
quantity: 2,
unitPrice: 17.69,
upc: 123458,
status: 'Not Processed'
}
]
}
];
System.config({
//use typescript for compilation
transpiler: 'typescript',
//typescript compiler options
typescriptOptions: {
emitDecoratorMetadata: true
},
paths: {
'npm:': 'https://unpkg.com/'
},
//map tells the System loader where to look for things
map: {
'app': './src',
'@angular/core': 'npm:@angular/core/bundles/core.umd.js',
'@angular/common': 'npm:@angular/common/bundles/common.umd.js',
'@angular/compiler': 'npm:@angular/compiler/bundles/compiler.umd.js',
'@angular/platform-browser': 'npm:@angular/platform-browser/bundles/platform-browser.umd.js',
'@angular/platform-browser-dynamic': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic.umd.js',
'@angular/http': 'npm:@angular/http/bundles/http.umd.js',
'@angular/router': 'npm:@angular/router/bundles/router.umd.js',
'@angular/forms': 'npm:@angular/forms/bundles/forms.umd.js',
'@angular/core/testing': 'npm:@angular/core/bundles/core-testing.umd.js',
'@angular/common/testing': 'npm:@angular/common/bundles/common-testing.umd.js',
'@angular/compiler/testing': 'npm:@angular/compiler/bundles/compiler-testing.umd.js',
'@angular/platform-browser/testing': 'npm:@angular/platform-browser/bundles/platform-browser-testing.umd.js',
'@angular/platform-browser-dynamic/testing': 'npm:@angular/platform-browser-dynamic/bundles/platform-browser-dynamic-testing.umd.js',
'@angular/http/testing': 'npm:@angular/http/bundles/http-testing.umd.js',
'@angular/router/testing': 'npm:@angular/router/bundles/router-testing.umd.js',
'rxjs': 'npm:rxjs',
'typescript': 'npm:typescript@2.0.2/lib/typescript.js'
},
//packages defines our app package
packages: {
app: {
main: './main.ts',
defaultExtension: 'ts'
},
rxjs: {
defaultExtension: 'js'
}
}
});
.jumbotron-n{
background-color: #aaa;
}
.info-label{
background-color: #aaa;
padding: 15px;
border-right:1px solid #999;
}
.info-value{
background-color: #ccc;
padding: 15px;
}
.info-label-val{
background-color: #ddd;
padding: 15px;
border:1px solid #999;
}
.info-value-i{
background-color: #ccc;
padding: 8px;
}
.info-col{
padding: 0 30px;
}
.notification{
padding: 5px 5px 15px 5px;
}
.notification .activeItem{
padding: 5px;
background: #fabf2d;
color: #202020;
}
.notification .success{
padding: 2px;
background: #33FF86;
color: #202020;
}
.orderitems{
padding: 5px 20px;
}
.itemDetailsContainer{
padding: 20px;
background-color: #aaa;
}
.itemDetails{
padding: 10px 20px;
border: 2px solid #ccc;
border-radius:10px;
}
.info-col-d .info-label, .info-col-d .info-value{
border-bottom: 1px solid #333;
}
.div-button {
text-align: center;
margin 0 auto;
background-color: #333;
color:#ccc;
border-radius:10px;
padding: 10px;
}
.app-alert-danger{
text-align: left;
margin 0 auto;
color:#ff9999;
padding: 2px;
background-color: #ffe6e6;
}
.div-row-10{
padding: 10px 0;
}
<div class="itemDetails">
<h4> Selected Item : {{item.name}} </h4>
<div class="row">
<div class="col-xs-12 info-col-d">
<div class="col-xs-3 info-label-val">Product # {{item.id}}</div>
<div class="col-xs-3 info-label-val">Quantity: {{item.quantity || ' '}}</div>
<div class="col-xs-3 info-label-val">Unit Price ${{item.unitPrice || ' '}}</div>
<div class="col-xs-3 info-label-val">UPC {{item.upc}}</div>
</div>
</div>
<div class="row" style="padding-top:10px;">
<div class="col-xs-6 info-label"><span id="item-barcode-label">Enter Scanned UPC #</span></div>
<div class="col-xs-6 info-value-i">
<input type="text" class="form-control" id="item-barcode"
[(ngModel)]="scannedUPC"
aria-describedby="item-barcode-label">
</div>
</div>
<div class="row" style="padding-top:10px;">
<div class="col-xs-6 info-label">
<span id="item-quantity-label">Quantity to be added to supply Cart</span>
</div>
<div class="col-xs-6 info-value-i">
<input type="number" class="form-control" id="item-quantity" name="item-quantity"
aria-describedby="item-quantity-label" [(ngModel)]="suppliedQuantity">
</div>
</div>
<div class="row" style="padding-top:10px;">
<div class="col-xs-12">
<div class="div-button" (click)="processItem()">Process Item</div>
</div>
</div>
<div class="div-row-10">
<div class="app-alert-danger" *ngFor="let err of errors" >{{err}}</div>
</div>
</div>
import {Component,Input, OnChanges, SimpleChanges, SimpleChange} from '@angular/core';
@Component({
selector: 'item-details',
templateUrl: 'src/components/item-details/item-details.html',
})
export class ItemDetails implements OnChanges {
private _item;
get item(): any {
return this._item;
}
@Input()
set item(val: any) {
console.log('previous item = ', this._item);
console.log('currently selected item=', val);
this._item = val;
this._item.status = 'In Process';
}
@Input() notifyItemProcessed: () => void;
suppliedQuantity: number;
scannedUPC: string;
errors: string[];
constructor(){
this.suppliedQuantity = 0;
this.scannedUPC = '';
}
ngOnChanges(changes: SimpleChanges) {
console.log('inside ngOnChanges', changes);
const currentItem: SimpleChange = changes.item;
console.log('prev value: ', currentItem.previousValue);
console.log('got item: ', currentItem.currentValue);
if(currentItem.currentValue){
this.scannedUPC = changes.item.currentValue.upc;
}
this.suppliedQuantity = 0;
}
processItem = () => {
this.errors = [];
if(this.suppliedQuantity < 1){
this.errors.push('Supplied quantity cannot be less than 0');
}
if(this.suppliedQuantity > this.item.quantity){
this.errors.push('Supplied quantity cannot be more than ordered qunatity');
}
if(this.scannedUPC != this.item.upc){
this.errors.push('ScannedUPC not matching with product UPC');
}
if (this.errors.length > 0){
return false;
}
if (!this.item.quantityInCart){
this.item['quantityInCart'] = this.suppliedQuantity;
}
this.suppliedQuantity = 0;
this.scannedUPC = '';
this.notifyItemProcessed();
}
}