Skip to content

Commit

Permalink
Reformatting
Browse files Browse the repository at this point in the history
  • Loading branch information
DeborahK committed Apr 27, 2019
1 parent 43077a4 commit adbe966
Show file tree
Hide file tree
Showing 4 changed files with 55 additions and 45 deletions.
49 changes: 28 additions & 21 deletions APM/src/app/products/product-detail/product-detail.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import { catchError, map, filter } from 'rxjs/operators';

import { ProductService } from '../product.service';
import { Product } from '../product';
import { combineLatest, of, Subject } from 'rxjs';
import { combineLatest, of, Subject, Observable } from 'rxjs';

@Component({
selector: 'pm-product-detail',
Expand All @@ -14,31 +14,38 @@ import { combineLatest, of, Subject } from 'rxjs';
export class ProductDetailComponent {
error$ = new Subject<string>();

selectedProductId$ = this.productService.productSelectedAction$;

product$ = this.productService.selectedProduct$.pipe(
catchError(error => {
this.error$.next(error);
return of(null);
}));
product$: Observable<Product> = this.productService.selectedProduct$
.pipe(
catchError(error => {
this.error$.next(error);
return of(null);
}));

// Set the page title
pageTitle$ = this.product$.pipe(
map((p: Product) => p ? `Product Detail for: ${p.productName}` : null)
);

productSuppliers$ = this.productService.selectedProductSuppliers$.pipe(
catchError(error => {
this.error$.next(error);
return of(null);
}));
pageTitle$ = this.product$
.pipe(
map((p: Product) =>
p ? `Product Detail for: ${p.productName}` : null)
);

productSuppliers$ = this.productService.selectedProductSuppliers$
.pipe(
catchError(error => {
this.error$.next(error);
return of(null);
}));

// Create a combined stream with the data used in the view
// Use filter to skip if the product is null
vm$ = combineLatest([this.product$, this.productSuppliers$, this.pageTitle$]).pipe(
filter(([product]) => product),
map(([product, productSuppliers, pageTitle]) => ({ product, productSuppliers, pageTitle }))
);
vm$ = combineLatest(
[this.product$,
this.productSuppliers$,
this.pageTitle$])
.pipe(
filter(([product]) => !!product),
map(([product, productSuppliers, pageTitle]) =>
({ product, productSuppliers, pageTitle }))
);

constructor(private productService: ProductService) { }

Expand Down
6 changes: 3 additions & 3 deletions APM/src/app/products/product-list/product-list.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,12 @@
</div>

<div class='card-body'
*ngIf="products$ | async as products">
*ngIf="vm$ | async as vm">
<div class='list-group'>
<button type='button'
class='list-group-item'
*ngFor='let product of products'
[ngClass]="{'active': product?.id === (selectedProductId$ | async)}"
*ngFor='let product of vm.products'
[ngClass]="{'active': product?.id === vm.productId}"
(click)='onSelected(product.id)'>
{{ product.productName }} ({{ product.category }})
</button>
Expand Down
26 changes: 17 additions & 9 deletions APM/src/app/products/product-list/product-list.component.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
import { Component, OnInit, ChangeDetectionStrategy } from '@angular/core';
import { Router, ActivatedRoute } from '@angular/router';

import { of, Subject } from 'rxjs';
import { catchError } from 'rxjs/operators';
import { of, Subject, Observable, combineLatest } from 'rxjs';
import { catchError, filter, map, tap } from 'rxjs/operators';

import { ProductService } from '../product.service';
import { Product } from '../product';

@Component({
selector: 'pm-product-list',
Expand All @@ -15,19 +16,26 @@ export class ProductListComponent implements OnInit {
pageTitle = 'Products';
error$ = new Subject<string>();

products$ = this.productService.productsWithCategory$.pipe(
catchError(error => {
this.error$.next(error);
return of(null);
}));
products$: Observable<Product[]> = this.productService.productsWithCategory$
.pipe(
catchError(error => {
this.error$.next(error);
return of(null);
}));

selectedProductId$ = this.productService.productSelectedAction$;
selectedProduct$ = this.productService.selectedProduct$;

vm$ = combineLatest([this.products$, this.selectedProduct$])
.pipe(
map(([products, product]: [Product[], Product]) =>
({ products, productId: product ? product.id : 0 }))
);

constructor(
private route: ActivatedRoute,
private router: Router,
private productService: ProductService
) {}
) { }

ngOnInit(): void {
// Read the parameter from the route - supports deep linking
Expand Down
19 changes: 7 additions & 12 deletions APM/src/app/products/product.service.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';

import { combineLatest, ReplaySubject, throwError, of } from 'rxjs';
import { catchError, map, shareReplay, tap, startWith } from 'rxjs/operators';
import { combineLatest, throwError, of, BehaviorSubject } from 'rxjs';
import { catchError, map, shareReplay, tap, switchMap } from 'rxjs/operators';

import { Product } from './product';
import { ProductCategory } from '../product-categories/product-category';
Expand Down Expand Up @@ -39,27 +39,22 @@ export class ProductService {
p =>
({
...p,
category: categories.find(c => p.categoryId === c.id).name
category: categories.find(c =>
p.categoryId === c.id).name
} as Product) // <-- note the type here!
)
),
shareReplay()
);

// Use ReplaySubject to "replay" values to new subscribers
// ReplaySubject buffers the defined number of values, in this case 1.
// Retains the currently selected product Id
// Uses 0 for no selected product (can't use null because it is used as a route parameter)
private productSelectedAction = new ReplaySubject<number>(1);
// Expose the selectedProduct as an observable for use by any components
productSelectedAction$ = this.productSelectedAction.asObservable().pipe(startWith(0));
private productSelectedAction = new BehaviorSubject<number>(0);

// Currently selected product
// Used in both List and Detail pages,
// so use the shareReply to share it with any component that uses it
// Location of the shareReplay matters ... won't share anything *after* the shareReplay
selectedProduct$ = combineLatest(
this.productSelectedAction$,
this.productSelectedAction,
this.productsWithCategory$
).pipe(
map(([selectedProductId, products]) =>
Expand All @@ -79,7 +74,7 @@ export class ProductService {
supplier => product ? product.supplierIds.includes(supplier.id) : of(null)
)
)
)
);

constructor(
private http: HttpClient,
Expand Down

0 comments on commit adbe966

Please sign in to comment.