Skip to content

Commit cc1264e

Browse files
committed
edit product and pub sub service
- enabled edit product - added pub sub service for communicating between product add/edit component and product list component - refactored animations
1 parent 98e7883 commit cc1264e

17 files changed

+114
-47
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
# angular2-animation-tutorial-example
22

3-
Angular 2 / 4 - Router Animation Example & Tutorial
3+
Angular 2/4 - Router Animation Example & Tutorial

app/_animations/fade-in.animation.ts

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { trigger, state, animate, transition, style } from '@angular/animations';
2+
3+
export const fadeInAnimation =
4+
trigger('fadeInAnimation', [
5+
// route 'enter' transition
6+
transition(':enter', [
7+
8+
// styles at start of transition
9+
style({ opacity: 0 }),
10+
11+
// animation and styles at end of transition
12+
animate('.3s', style({ opacity: 1 }))
13+
]),
14+
]);

app/_animations/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './fade-in.animation';
2+
export * from './slide-in-out.animation';

app/_helpers/animations.ts renamed to app/_animations/slide-in-out.animation.ts

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,7 @@
11
import { trigger, state, animate, transition, style } from '@angular/animations';
22

3-
export function fadeIn() {
4-
return trigger('fadeIn', [
5-
// route 'enter' transition
6-
transition(':enter', [
7-
8-
// styles at start of transition
9-
style({ opacity: 0 }),
10-
11-
// animation and styles at end of transition
12-
animate('.3s', style({ opacity: 1 }))
13-
]),
14-
]);
15-
}
16-
17-
export function slideInOut() {
18-
return trigger('slideInOut', [
3+
export const slideInOutAnimation =
4+
trigger('slideInOutAnimation', [
195

206
// end state styles for route container (host)
217
state('*', style({
@@ -62,5 +48,4 @@ export function slideInOut() {
6248
backgroundColor: 'rgba(0, 0, 0, 0)'
6349
}))
6450
])
65-
])
66-
}
51+
]);

app/_services/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1 +1,2 @@
11
export * from './product.service';
2+
export * from './pub-sub.service';

app/_services/product.service.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ export class ProductService {
77
}
88

99
getById(id: number) {
10-
return this.getProducts().filter(product => product.id === id);
10+
return this.getProducts().find(product => product.id === id);
1111
}
1212

1313
save(product: any) {

app/_services/pub-sub.service.ts

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { Injectable } from '@angular/core';
2+
import { Observable } from 'rxjs';
3+
import { Subject } from 'rxjs/Subject';
4+
5+
@Injectable()
6+
export class PubSubService {
7+
private subjects: Subject<any>[] = [];
8+
9+
publish(eventName: string) {
10+
// ensure a subject for the event name exists
11+
this.subjects[eventName] = this.subjects[eventName] || new Subject<any>();
12+
13+
// publish event
14+
this.subjects[eventName].next();
15+
}
16+
17+
on(eventName: string): Observable<any> {
18+
// ensure a subject for the event name exists
19+
this.subjects[eventName] = this.subjects[eventName] || new Subject<any>();
20+
21+
// return observable
22+
return this.subjects[eventName].asObservable();
23+
}
24+
}

app/app-routing.module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,8 @@ const routes: Routes = [
1010
path: 'products',
1111
component: ProductListComponent,
1212
children: [
13-
{ path: 'add', component: ProductAddEditComponent }
13+
{ path: 'add', component: ProductAddEditComponent },
14+
{ path: 'edit/:id', component: ProductAddEditComponent }
1415
]
1516
},
1617

app/app.module.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
55

66
import { AppComponent } from './app.component';
77
import { AppRoutingModule, routedComponents } from './app-routing.module';
8-
import { ProductService } from './_services/index';
8+
import { ProductService, PubSubService } from './_services/index';
99

1010
@NgModule({
1111
imports: [
@@ -19,7 +19,8 @@ import { ProductService } from './_services/index';
1919
routedComponents
2020
],
2121
providers: [
22-
ProductService
22+
ProductService,
23+
PubSubService
2324
],
2425
bootstrap: [AppComponent]
2526
})

app/home/home.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
<h1>Home</h1>
2-
<p>Angular 2 (version 4) Animation Tutorial & Example</p>
2+
<p>Angular 2/4 - Animation Tutorial & Example</p>

app/home/home.component.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,12 @@
11
import { Component } from '@angular/core';
2-
import { fadeIn } from '../_helpers/animations';
2+
3+
import { fadeInAnimation } from '../_animations/index';
34

45
@Component({
56
moduleId: module.id.toString(),
67
templateUrl: 'home.component.html',
7-
animations: [fadeIn()],
8-
host: { '[@fadeIn]': '' }
8+
animations: [fadeInAnimation],
9+
host: { '[@fadeInAnimation]': '' }
910
})
1011

1112
export class HomeComponent {

app/products/product-add-edit.component.html

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
11
<div class="side-form">
22
<h1>{{title}}</h1>
33
<div class="form-container">
4-
<form method="post">
4+
<form (ngSubmit)="saveProduct()">
55
<div class="form-group">
66
<label for="name">Name</label>
7-
<input type="text" id="name" class="form-control" required />
7+
<input type="text" name="name" [(ngModel)]="product.name" class="form-control" required />
88
</div>
99
<div class="form-group">
1010
<label for="name">Price</label>
11-
<input type="text" id="price" class="form-control" required />
11+
<input type="text" name="price" [(ngModel)]="product.price" class="form-control" required />
1212
</div>
1313
<div class="form-group">
1414
<a class="btn btn-default" routerLink="/products">Cancel</a>
Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,42 @@
1-
import { Component } from '@angular/core';
2-
import { slideInOut } from '../_helpers/animations';
1+
import { Component, OnInit } from '@angular/core';
2+
import { Router, ActivatedRoute } from '@angular/router';
3+
4+
import { slideInOutAnimation } from '../_animations/index';
5+
import { ProductService, PubSubService } from '../_services/index';
36

47
@Component({
58
moduleId: module.id.toString(),
69
templateUrl: 'product-add-edit.component.html',
7-
animations: [slideInOut()],
8-
host: { '[@slideInOut]': '' }
10+
animations: [slideInOutAnimation],
11+
host: { '[@slideInOutAnimation]': '' }
912
})
1013

11-
export class ProductAddEditComponent {
12-
title: string = "Add Product";
14+
export class ProductAddEditComponent implements OnInit {
15+
title = "Add Product";
16+
product: any;
17+
18+
constructor(
19+
private route: ActivatedRoute,
20+
private router: Router,
21+
private productService: ProductService,
22+
private pubSubService: PubSubService) { }
23+
24+
ngOnInit() {
25+
let productId = Number(this.route.snapshot.params['id']);
26+
if (productId) {
27+
this.title = 'Edit Product';
28+
this.product = this.productService.getById(productId);
29+
}
30+
}
31+
32+
saveProduct() {
33+
// save product
34+
this.productService.save(this.product);
35+
36+
// redirect to users view
37+
this.router.navigate(['products']);
38+
39+
// publish event so list controller can refresh
40+
this.pubSubService.publish('products-updated');
41+
}
1342
}

app/products/product-list.component.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
<th class="delete-column"></th>
88
</tr>
99
<tr *ngFor="let product of products">
10-
<td><a>{{product.name}}</a></td>
10+
<td><a [routerLink]="['edit', product.id]">{{product.name}}</a></td>
1111
<td>${{product.price}}</td>
1212
<td><a class="btn btn-xs btn-danger">Delete</a></td>
1313
</tr>

app/products/product-list.component.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,23 @@
1-
import { Component, OnInit } from '@angular/core';
1+
import { Component, OnInit, OnDestroy } from '@angular/core';
2+
import { Subscription } from 'rxjs/Subscription';
23

3-
import { fadeIn } from '../_helpers/animations';
4-
import { ProductService } from '../_services/index';
4+
import { fadeInAnimation } from '../_animations/index';
5+
import { ProductService, PubSubService } from '../_services/index';
56

67
@Component({
78
moduleId: module.id.toString(),
89
templateUrl: 'product-list.component.html',
9-
animations: [fadeIn()],
10-
host: { '[@fadeIn]': '' }
10+
animations: [fadeInAnimation],
11+
host: { '[@fadeInAnimation]': '' }
1112
})
1213

13-
export class ProductListComponent implements OnInit {
14+
export class ProductListComponent implements OnInit, OnDestroy {
1415
products: any[];
16+
subscription: Subscription;
1517

16-
constructor(private productService: ProductService) { }
18+
constructor(
19+
private productService: ProductService,
20+
private pubSubService: PubSubService) { }
1721

1822
deleteProduct(id: number) {
1923
this.productService.delete(id);
@@ -24,7 +28,12 @@ export class ProductListComponent implements OnInit {
2428
this.loadProducts();
2529

2630
// reload products when updated
27-
// $scope.$on('products-updated', loadProducts);
31+
this.subscription = this.pubSubService.on('products-updated').subscribe(() => this.loadProducts());
32+
}
33+
34+
ngOnDestroy() {
35+
// unsubscribe to ensure no memory leaks
36+
this.subscription.unsubscribe();
2837
}
2938

3039
private loadProducts() {

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
<html>
33
<head>
44
<base href="/" />
5-
<title>Angular 2 Animation Tutorial & Example</title>
5+
<title>Angular 2/4 - Animation Tutorial & Example</title>
66
<meta name="viewport" content="width=device-width, initial-scale=1">
77

88
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.5/css/bootstrap.min.css" rel="stylesheet" />

systemjs.config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/**
2-
* System configuration for Angular 2 samples
2+
* System configuration for Angular 2/4 samples
33
* Adjust as necessary for your application needs.
44
*/
55
(function (global) {

0 commit comments

Comments
 (0)