Reputation: 763
I have an array of 5 persons in my json file. Each person has an array with items in it. In my html code, I'm using *ngFor to loop through the persons to show their name. I also want to show the sum of the prices of the items. To calculate the prices of their items together, I use a function in my TypeScript code. I'm showing the total of the prices in my console.
The problem is, that the current code I'm using in my typescript file loops through the persons again. So I'm looping through the persons in my html with *ngFor and in this I'm calling the function getTotal(), which loops through the persons again. Of course I want to loop through them only once.
json
"persons":[
{
"name": "Peter",
"items": [
{
"name": "pen",
"price": 1.50
},
{
"name": "paper",
"price": 2.00
}
]
},
{
"name": "Maria",
"items": [
{
"name": "scissors",
"price": 4.00
},
{
"name": "stickers",
"price": 3.00
}
]
}
// three more persons
]
html
<div *ngFor="let person of persons"> <!--here I'm looping through the persons-->
<p>{{person.name}}</p>
<p>Total <span>{{getTotal()}}</span></p> <!--here I'm calling the function, which will loop through persons again-->
</div>
typescript
getTotal() {
for(let person of this.persons){ //here I'm looping through the persons again (what I actually don't want)
let total = 0;
for(let item of person.items){
total = total + item.price;
}
console.log(total);
}
}
Now to my question: As you can see, I was looping through persons in my html code with *ngFor and in my typescript code in getTotal() again. I only did that to access their items in the following loop (person.items). I wanna get rid of the first loop and access the current element I'm looping through with *ngFor. How can I achieve this or is it even possible?
Upvotes: 0
Views: 2926
Reputation: 58553
Just Change It like
As answer to your question , call a function from template side , here it is but would prefer second method to go
Template Side :
<p>Total <span>{{getTotal(person.items)}}</span></p>
Component Side :
getTotal(items) {
let total = 0 ;
for(let item of items){
total = total + item.price;
}
return total;
}
Better way to do is , process all data from component side , rather than calling it from template side
Why ?
In above case function will be called each time the view changes or data change.
Component Side :
constructor(){
this.persons.map(person => {
person.total = person.items.reduce((pv,cv) => {
return cv.price + pv.price;
});
return person;
});
}
Template Side :
<p>Total <span>{{person.total)}}</span></p>
Upvotes: 2
Reputation: 329
Send to the getTotal method the person. I mean:
getTotal(person:any){
let total: number = 0;
for(item of person.items){
total += item.price;
}
return total;
}
So in your HTML it must be:
<div *ngFor="let person of persons">
<p>{{person.name}}</p>
<p>Total <span>{{getTotal(person)}}</span></p> <!-- take a look how
I send the current person in the *ngFor loop -->
</div>
Upvotes: 1
Reputation: 36703
You can pass person in the getTotal
function and can add the price of the items in that without looping again
<div *ngFor="let person of persons">
<p>{{person.name}}</p>
<p>Total <span>{{ getTotal(person) }}</span></p> <!--here I'm calling the function, which will loop through persons again-->
</div>
Typescript
getTotal(person) {
let total = 0;
for(let item of person.items){
total = total + item.price;
}
return total;
}
Upvotes: 1