Reputation: 338
import {
Component,
OnInit
} from "@angular/core";
import {
MarkService
} from "../app/services/marks.service";
@Component({
selector: "app-root",
templateUrl: "./app.component.html",
styleUrls: ["./app.component.scss"]
})
export class AppComponent implements OnInit {
title = "my-test";
public students = [];
allStudents: any = [];
average: any = [];
constructor(private _marksService: MarkService) {}
ngOnInit() {
this._marksService.getMarks().subscribe(data => (this.students = data));
}
calHandle(i) {
var data = this.students;
this.average = Object.values(data).reduce(
(avg, {
values
}, _, {
length
}) => avg + values / length,
0
);
}
}
<table border="1">
<tr>
<th>Name</th>
<th>Jan</th>
<th>Feb</th>
<th>March</th>
<th>April</th>
<th>action</th>
<th>Average</th>
<!-- </tr> -->
<tbody *ngFor="let item of students; let i = index;">
<tr>
<td>{{item.name}}</td>
<td>{{item.jan}}</td>
<td>{{item.feb}}</td>
<td>{{item.march}}</td>
<td>{{item.April}}</td>
<td><button (click)="calHandle(i)">calculate</button></td>
<td>{{average}}</td>
</tr>
</tbody>
</table>
<!--
json data
[
{"name": "josh", "jan":20,"feb":32, "march":"50", "April":45},
{"name": "peter", "jan":20,"feb":32, "march":"50", "April":45},
{"name": "gorge", "jan":20,"feb":32, "march":"50", "April":45}
]
-->
Above is my snippet for calculating the average of students on click event but whenever I am clicking on the button "calculate" the result I am getting is "NaN" so I am a little bit unsure that how do I provide only number value to prevent "NaN" error and what should I do for getting average of a particular student on button click.
Upvotes: 1
Views: 2700
Reputation: 22213
Try like this:
.ts
calHandle(i: number) {
var sum = 0;
var keys = Object.keys(this.students[i]);
keys.forEach(key => {
if (key != "name") {
sum += Number(this.students[i][key]);
}
});
this.students[i].average = sum / (keys.length - 1);
}
.html
<table border="1">
<tr>
<th>Name</th>
<th>Jan</th>
<th>Feb</th>
<th>March</th>
<th>April</th>
<th>action</th>
<th>Average</th>
</tr>
<tbody *ngFor="let item of students; let i = index;">
<tr>
<td>{{item.name}}</td>
<td>{{item.jan}}</td>
<td>{{item.feb}}</td>
<td>{{item.march}}</td>
<td>{{item.April}}</td>
<td><button (click)="calHandle(i)">calculate</button></td>
<td>{{item.average}}</td>
</tr>
</tbody>
</table>
Upvotes: 2
Reputation: 5940
You could use Object.entries
to check the key of your object and omit it if it is 'name'
:
const result = [
{"name": "josh", "jan":20,"feb":32, "march":"50", "April":45},
{"name": "peter", "jan":20,"feb":32, "march":"50", "April":45},
{"name": "gorge", "jan":20,"feb":32, "march":"50", "April":45}
].map(getAverage);
function getAverage(obj) {
return Object.entries(obj).reduce((avg, obj, _, { length }) => obj[0] == 'name' ? avg : avg + obj[1] / length, 0);
}
console.log(result);
So in your case it would be:
calHandle(i) {
var data = this.students;
this.average = Object.entries(data).reduce(
(avg, obj, _, {
length
}) => obj[0] == 'name' ? avg : avg + obj[1] / length,
0
);
}
Upvotes: 0