I have the following Product object inside an Angular application. The product contains array of orders and other product information.
Product.ts
export interface Product {
ProductID: number;
ProductName: string;
Orders: Order[]
}
I need to display product information and generate order summary inside a child angular component.
order-summary.component.ts
export class OrderSummary {
_product: Product;
@Input() set product(value: Product) {
this._product = value;
this.generateOrderSummary(value.Orders);
}
private generateOrderSummary(orders: Order[]) {
// Logic to generate order summary
}
}
order-summary.component.html
<b>{{_product.ProductName}}</b>
<b> ... show other product details </b>
<table> ... show generated order summary ... </table>
I believe every time the product object changes, it will generate the order summary (generateOrderSummary
) even if the Orders
array hasn't been changed. What is a better way to fix this issue?
I am thinking of adding another property for Orders[] so I can regenerate summary only when order has been changed. However, product already contains orders not sure if it is a good design.
order-summary.component.ts
export class OrderSummary {
_product: Product;
@Input() set product(value: Product) {
this._product = value;
}
@Input() set orders(value: Orders[]) {
this.generateOrderSummary(value.Orders);
}
private generateOrderSummary(orders: Order[]) {
// Logic to generate order summary
}
}
Are there any better solutions?
In this case you could skip the setter implementation of the @Input
and use Angular OnChanges
hook with SimpleChanges
parameter. It allows you to check if it's the first invoke of the component and compare previous and current values of the @Input
property.
Try the following
order-summary.component.ts
import { Component, Input, OnChanges, SimpleChanges } from '@angular/core';
export class OrderSummary implements OnChanges {
@Input() product: Product;
ngOnChanges(changes: SimpleChanges) {
if (!!changes.product) {
if (changes.product.firstChange) { // <-- first time the component is rendered
this.generateOrderSummary(this.product.orders); // <-- could also be `changes.product.currentValue.orders`
} else if ( // <-- true only if different `orders` value
!!changes.product.previousValue &&
!!changes.product.previousValue.orders &&
changes.product.previousValue.orders !== changes.product.currentValue.orders
) {
this.generateOrderSummary(product.orders);
}
}
}
private generateOrderSummary(orders: Order[]) {
// Logic to generate order summary
}
}
order-summary.component.html
<b>{{ product?.ProductName }}</b>
<b> ... show other product details </b>
<table> ... show generated order summary ... </table>