It appears that the issue arises when cloning a class using object destructuring, resulting in the loss of the class instance which needs to be preserved.
PackingOrder = signal<Order>(hardCodedOrder);
constructor() {
effect(() => {
console.log('order changed', structuredClone(this.PackingOrder()));
});
}
ngOnInit() {
setTimeout(() => {
this.PackingOrder.update((order: Order) => {
const foundItem = order.orderItems.find(
(item: OrderItem) => item.packed === 2
);
if (foundItem) {
foundItem.unitQty = 10000;
// Trigger a signal change by returning a clone after updating.
return order.clone();
}
return order;
});
}, 5000);
}
My approach involves using the update
method to modify values within the signal, providing easy access to the order state.
We locate and update a specific order item using find
, ensuring its existence before changing the property (packed
updated to 10000
).
Note: Non-primitive data types like object
and array
are stored as references in memory. The signal only detects changes when the actual value is altered, requiring a shift in memory location.
To retain the class prototype while creating a new instance, I implemented a clone
method within the class instance. This method generates a new instance with identical data.
export class Order {
id: number;
customer: string;
orderItems: OrderItem[];
constructor(id: number, customer: string, orderItems: OrderItem[] = []) {
this.id = id;
this.customer = customer;
this.orderItems = orderItems;
}
clone() {
const clone = Object.assign({}, this);
return Object.setPrototypeOf(clone, Order.prototype);
// Uncomment below code for an alternative approach.
// return new Order(this.id, this.customer, this.orderItems);
}
Now, utilizing the clone method within the update function triggers a refresh in the signal following data updates.
The use of structuredClone
ensures accurate snapshots of updated data in the Chrome console.
Complete Code:
import { Component, effect, signal } from '@angular/core';
import { bootstrapApplication } from '@angular/platform-browser';
// Include Order and OrderItem classes...
// Set up hard-coded initial Order...
@Component({
selector: 'app-root',
template: `
<a target="_blank" href="https://angular.dev/overview">
Learn more about Angular
</a>
`,
})
export class App {
PackingOrder = signal<Order>(hardCodedOrder);
constructor() {
effect(() => {
console.log('order changed', structuredClone(this.PackingOrder()));
});
}
ngOnInit() {
setTimeout(() => {
this.PackingOrder.update((order: Order) => {
const foundItem = order.orderItems.find(
(item: OrderItem) => item.packed === 2
);
if (foundItem) {
foundItem.unitQty = 10000;
// If updated, trigger a signal change via object destructuring.
return order.clone();
}
return order;
});
}, 5000);
}
}
bootstrapApplication(App);