Im trying to display total counts of enrollment with item.male_students
& item.female_students
UPDATE
remove the ngFor now it works as expected.
here's my component.html
<thead >
<tr>
<th>
Total Enrollment Quick Count
</th>
</tr>
</thead>
<tbody >
<tr>
<td>
{{ item.male_students item.female_students }}
</td>
</tr>
</tbody>
UPDATED
here's my component.ts
data: [];
constructor(private apiService: ApiService) {
super();
}
ngOnInit(): void {
this.getEnrollMentCountBySex();
}
getEnrollMentCountBySex() {
this.apiService.getAll('enrollments', "/count-student-enrollment-by-sex-and-academic-level")
.subscribe(data => {
this.data = data;
this.maleCount = data.reduce(((acc, item) => acc item.male_students), 0);
this.femaleCount = data.reduce(((acc, item) => acc item.female_students), 0);
});
}
Im getting object. Here's and image from api endpoint
UPDATE
But im getting all the index. I only want the total count of male & female students to be shown in table
CodePudding user response:
You can do it as soon as you receive data from ajax. That's the good way I would suggest you in this case.
getEnrollMentCountBySex() {
this.apiService.getAll('enrollments', "/count-student-enrollment-by-sex-and-academic-level").subscribe(data => {
this.data = data;
this.maleCount = data.reduce((acc, item) => acc item.male_students), 0);
this.femaleCount = data.reduce((acc, item) => acc item.female_students), 0);
});
}
HTML
Male Count - {{ maleCount }}
Female Count - {{ femaleCount }}
If data
is being modified from user
in your case and we wanted to keep UI bindings updated. Then definitely using Pipe
or function
call on binding would be a better idea.
@Pipe({name: 'countByProp'})
export class CountByPropPipe implements PipeTransform {
transform(data: any, prop: string): number {
if (!prop) throw new Error('Please pass property name');
return data.reduce((acc, item) => acc item[prop]), 0);
}
}
HTML
Male Count - {{ data | countByProp: 'male_students' }}
Female Count - {{ data | countByProp: 'female_students' }}
TS
Define maleCount
and femaleCount
variable in your HomePage.ts
maleCount = 0;
femaleCount = 0;
CodePudding user response:
I wrote a slightly different approach. (though I would also prefer using pipes). Here we use | async
pipe which takes care of unsubscribe and using tap
we create a sideeffect and calculate totals of from the data
.
<tbody >
<tr *ngFor="let item of data$ | async; let i = index">
<td>
{{ item.male_students item.female_students }}
</td>
</tr>
total males: {{totalMaleStudents}}
total females: {{totalFemaleStudents}}
</tbody>
@Component({
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: ['./app.component.css'],
})
export class AppComponent implements OnInit {
data$: any;
totalFemaleStudents = 0;
totalMaleStudents = 0;
ngOnInit() {
const apiData = [
{ name: 'elementary', id: 1, female_students: 1, male_students: 1 },
{ name: 'highschool', id: 2, female_students: 0, male_students: 0 },
{ name: 'junior', id: 3, female_students: 0, male_students: 0 },
];
// mock
this.data$ = of(apiData).pipe(
tap((data) => {
console.log(data);
// validate
if (!Array.isArray(data)) {
return;
}
// calculate
for (let i = 0; i < data.length - 1; i ) {
if (data[i]?.female_students) {
this.totalFemaleStudents = data[i]?.female_students;
}
if (data[i]?.male_students) {
this.totalMaleStudents = data[i]?.male_students;
}
}
})
);
}
}
Working example: https://stackblitz.com/edit/angular-ivy-nvw55f?file=src/app/app.component.ts