我们在本节会继续完善产品详情页面,
- 增加Buy按钮
- 创建shopping cart组件
- 使用HttpClient来获取shipping数据
创建 shopping cart service
定义cart service
-
运行如下的命令来创建cart service
ng generate service cart -
在cart service中,定义一个属性items,用来存储shopping cart里的产品。
export class CartService { items: Product[] = []; } -
定义三个方法,分别用来添加产品购物车,获取购物车里的数据和清空购物车。
export class CartService { items: Product[] = []; constructor() { } addToCart (product: Product) { this.items.push(product); } getItems() { return this.items; } clearCart() { this.items = []; return this.items; } }
使用cart service
-
注入cart service 到product-details组件。
export class ProductDetailsComponent { product: Product | undefined; constructor( private route: ActivatedRoute, private readonly productsService: ProductsService, private readonly cartService: CartService ){} } -
定义addToCart()方法,用来把产品添加到购物车。
export class ProductDetailsComponent implements OnInit { addToCart(product: Product) { this.cartService.addToCart(product); window.alert('Your product has been added to the cart!'); } } -
修改product-details组件的HTML页面,添加一个Buy按钮,并且绑定click()事件到addToCart()方法。
<h2>Product Details</h2> <div *ngIf="product"> <h3>{{product.name}}</h3> <h4>{{product.price | currency}}</h4> <p>{{product.description}}</p> <button type="button" (click)="addToCart(product)">Buy</button> </div> -
验证Buy按钮是否工作正常。
创建cart组件
-
运行如下命令来创建cart组件。
ng generate component cart -
在app-routing.module.ts里为cart组件添加一个新的路由。
const routes: Routes = [ { path: '', component: ProductListComponent }, { path: 'products/:productId', component: ProductDetailsComponent }, { path: 'cart', component: CartComponent} ]; -
在文件top-bar.component.html里,给Checkout按钮绑定routerLink属性到新增的路由。
<button type="submit" routerLink="/cart"><img src="assets/images/checkout.png" alt="Checkout" title="Checkout"> <span>Checkout</span> </button> -
验证Checkout按钮是否工作正常。
显示购物车详情
-
在cart组件类里注入Cart service,并定义一个属性items来获取购物车里的数据。
export class CartComponent { items = this.cartService.getItems(); constructor( private readonly cartService: CartService ){} } -
修改HTML页面,显示产品的信息。
<h3>Cart</h3> <div class="cart-item" *ngFor="let item of items"> <span>{{ item.name }}</span> <span>{{ item.price | currency }}</span> </div> -
验证购物车是否工作正常。
获取运输费用
本章将演示如何使用HttpClient从外部文件来获取运输费用。
-
在文件夹assets里创建文件shipping.json,并输入如下数据。
[ { "type": "Overnight", "price": 25.99 }, { "type": "2-Day", "price": 9.99 }, { "type": "Postal", "price": 2.99 }] -
配置AppModule来使用HttpClient。在文件app.module.ts中添加HttpClientModule的引用。
imports: [ BrowserModule, AppRoutingModule, HttpClientModule ], -
配置cart service以使用HttpClient。在cart service中注入HttpClient。
constructor( private readonly httpClient: HttpClient ) { } -
配置cart service来获取运输费用数据。在文件cart.service.ts中添加方法getShippingPrices(),使用HttpClient get()方法来获取运输费用数据。
getShippingPrices() { return this.httpClient.get<{ type: string, price: number }[]>('/assets/shipping.json'); }
创建shipping组件
-
运行如下命令创建shipping组件。
ng generate component shipping -
在文件app-routing.module.ts中创建新的路由指向shipping组件。
const routes: Routes = [ { path: '', component: ProductListComponent }, { path: 'products/:productId', component: ProductDetailsComponent }, { path: 'cart', component: CartComponent}, { path: 'shipping', component: ShippingComponent } ]; -
在文件shipping.component.ts中注入cart service。
constructor( private readonly cartService: CartService ) {} -
定义一个属性shippingCosts,并使用cart service的getShippingPrices()方法来获取该属性的值。
export class ShippingComponent { shippingCosts!: Observable<{ type: string, price: number }[]>; constructor( private readonly cartService: CartService ) {} ngOnInit(): void { this.shippingCosts = this.cartService.getShippingPrices(); } } -
更新shipping组件的HTML文件,显示运输的类型和价格。
<h3>Shipping Prices</h3> <div class="shippingItem" *ngFor="let item of shippingCosts | async"> <span>{{item.type}}</span> <span>{{item.price | currency}}</span> </div> -
在cart组件添加一个链接,用来跳转到shipping组件。
<p> <a routerLink="/shipping">Shipping Prices</a> </p> -
最终的效果如下图。