In my Application I have a ngrx store which contains an array of objects. In my constructor I am selecting the array and calling a method (onProductEntriesLoaded) which sets a variable to this array. In the html Code there is a *ngFor Loop that iterates through this variable and displays them. The method which sets the variable does also call another method which calculates a sum. However each time a add elements to this array in the state, the content is displayed correctly in the *ngFor loop. But the method which is setting the variable to the array is not called. It is only called at initialization. I thought that every part of the application which is subscribing to the state is loaded again whenever the state changes. Even if it is a constructor. However it doesn't seem to be like that. Could someone please explain me this behavior.
This is part of my cart.component.html
<div id="middle">
<div class="entries">
<div *ngFor="let entry of productEntries">
<img
*ngIf="!entry.product.image"
src="../../../assets/img/esansBottles Kopie.png"
/>
<img
*ngIf="entry.product.image"
src="../../../assets/img/{{ entry.product.image }}"
/>
{{ entry.product.title }}
{{ entry.variation.option }}
{{ entry.variation.price }}
{{ entry.amount }}
</div>
</div>
</div>
<div id="bottom">
<div>Summe {{ sumOfCart }} €</div>
<button>Zur Kasse</button>
</div>
And that's basically the cart.component.ts file
export class CartComponent implements OnInit {
productEntries: ShoppingCartEntry[];
sumOfCart: number;
constructor(private store: Store<State>) {
this.store
.select(state => state.shoppingCartReducer.Entries)
.subscribe(data => this.onProductEntriesLoaded(data));
}
ngOnInit() {}
onProductEntriesLoaded(productEntries: ShoppingCartEntry[]) {
console.log("onProductEntreisLoaded called");
this.productEntries = productEntries;
console.log(productEntries);
console.log("next calculate sum");
this.calculateSum(productEntries);
console.log("after calculate sum");
}
calculateSum(shoppingCartEntries: ShoppingCartEntry[]) {
console.log("calculate sum called");
/*let sum = 0.0;
console.log(shoppingCartEntries);
if (shoppingCartEntries) {
shoppingCartEntries.forEach(element => {
sum = element.amount * element.variation.price + sum;
});
}
this.sumOfCart = sum;*/
}
And that's one part of my reducer.ts file
export function shoppingCartReducer(
state: ShoppinCartState = { CartIsOpen: false, Entries: [] },
action: ShoppingCartAction
) {
switch (action.type) {
case "CART_TOGGLE":
return {
...state,
CartIsOpen: !state.CartIsOpen
};
case "CART_CLOSE":
return {
...state,
CartIsOpen: false
};
case "CART_ADD_ENTRY":
return {
...state,
Entries: addEntryToCart(state.Entries, action.payload)
};
default:
return state;
}
}
function addEntryToCart(
currentEntries: ShoppingCartEntry[],
entry: ShoppingCartEntry
): ShoppingCartEntry[] {
//if currentEntries is null return empty array
if (currentEntries) {
// if entry is null return currentEntries
if (entry) {
// check if currentEntries contains entry
let index = currentEntries.findIndex(
x => x.product === entry.product && x.variation === entry.variation
);
if (index === -1) {
let newEntries = currentEntries;
newEntries.push(entry);
return newEntries;
} else {
currentEntries[index].amount += entry.amount;
return currentEntries;
}
} else {
return currentEntries;
}
} else {
return [];
}
}
The problem was caused in my reducer function. After removing the function call to addEntryToCart inside my reducer and implementing the functionality within the reducer the problem was solved. I still don't understand why calling a function caused the problem.
Thats how I solved it:
export function shoppingCartReducer(
state: ShoppinCartState = { CartIsOpen: false, Entries: [] },
action: ShoppingCartAction
) {
switch (action.type) {
case "CART_TOGGLE":
return {
...state,
CartIsOpen: !state.CartIsOpen
};
case "CART_CLOSE":
return {
...state,
CartIsOpen: false
};
case "CART_ADD_ENTRY":
let contains = state.Entries.findIndex(
entry =>
entry.product === action.payload.product &&
entry.variation === action.payload.variation
);
if (contains === -1) {
return {
...state,
Entries: [...state.Entries.concat(action.payload)]
};
} else {
return {
...state,
Entries: [
...state.Entries.map(entry =>
entry.product === action.payload.product &&
entry.variation === action.payload.variation
? {
product: entry.product,
variation: entry.variation,
amount: entry.amount + action.payload.amount
}
: entry
)
]
};
}
default:
return state;
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.