Reputation: 1699
I am updating product object from parent component. Somehow the child component does not detect the change and does not update it.
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 tried to declare changeDetection: ChangeDetectionStrategy.Default
explicitly but no luck.
As mentioned in the code, if I add JSON.parse(JSON.stringify(this.product1));
then it works. So it seems that I need to create a new object so change detection work. I think I can use spread operator (object.assign) to make sure it creates a new object. However, I am not sure how to update the product inside refreshProduct() method using spread operation.
I think the code will look like:
this.product1 = {...this.product1,
lastUpdated: data.lastUpdated,
orders: .... // --> Not sure how to loop through orders and update the payments
};
EDIT: I think I managed to do it.
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};
})
};
Please let me know if there is any better solution available.
Upvotes: 2
Views: 923
Reputation: 2078
Try to do like this:
refreshProduct() {
let temp: Product = {};
this.sub = this.productService.getTheLatestOrders().subscribe(
(data) => {
temp.lastUpdated = data.lastUpdated;
temp.orders.forEach(order => {
let latestOrderData = data.orders.find(d => d.orderId == order.orderId);
if(latestOrderData) {
order.payments = latestOrderData.payments;
}
});
this.product1 = temp;
});
}
}
In this way every time it will assign the updated value to product.
Upvotes: 1