When I update the product object from the parent component, the child component does not seem to detect the change and fails to update accordingly.
product.ts
export interface Product {
productId: number;
productName: string;
lastUpdated: string;
orders: Array<Order>
}
order.ts:
export interface Order {
orderId: number;
payments: Array<Payment>
}
payment.ts:
export interface Payment {
paymentId: number;
amount: Array<number>
}
parent.component.html
<product-details [(product)]="product1" (refreshProduct)="refreshProduct()"></product-details>
parent.component.ts
product1: Product = null;
refreshProduct() {
this.sub = this.productService.getTheLatestOrders().subscribe(
(data) => {
this.product1.lastUpdated = data.lastUpdated;
this.product1.orders.forEach(order => {
let latestOrderData = data.orders.find(d => d.orderId == order.orderId);
if(latestOrderData) {
order.payments = latestOrderData.payments;
}
});
// this.product1 = JSON.parse(JSON.stringify(this.product1)); --> It works if I add this
});
}
}
product-details.component.html (child component)
<button id="refresh" name="refresh" (click)="refresh()" />
Last Updated : {{product.lastUpdated}}
<ng-container *ngFor="let order of product.orders">
<ng-container *ngFor="let payment of order.payments">
{{payment.date}} - {{payment.amount}}
</ng-container>
</ng-container>
product-details.component.ts (child component)
@Input('product') product: Product;
@Output() refreshProduct = new EventEmitter<any>();
refresh() {
this.refreshProduct.emit();
}
I attempted to explicitly declare
changeDetection: ChangeDetectionStrategy.Default
, but it did not solve the issue.
As shown in the code, adding
JSON.parse(JSON.stringify(this.product1));
solves the problem. It appears that creating a new object is necessary for change detection to function properly. Using the spread operator (object.assign) can accomplish this task, but updating the product inside the refreshProduct() method using the spread operation remains unclear.
The potential solution could look like:
this.product1 = {...this.product1,
lastUpdated: data.lastUpdated,
orders: .... // --> Not sure how to loop through orders and update the payments
};
EDIT: I believe I have figured it out.
this.product1 = {...this.product1,
lastUpdated: data.lastUpdated,
orders: this.product1.orders.map((order) => {
let updatedOrder = data.orders.find(o => o.orderId == order.orderId);
return {...order, order.payments: updateOrder.payments};
})
};
If you have any better solutions available, please let me know.