#javascript #html #angular #html-table
#javascript #HTML #angular #html-таблица
Вопрос:
Я использую Angular 6 и html-таблицу. Я показал данные списка json в таблице. Я хочу показать общее количество абитуриентов с учетом факультета в отдельном столбце («Общее количество преподавателей»), но я не могу этого сделать. Пожалуйста, помогите мне решить эту проблему.
Я хочу сделать так:
мой ts-файл:
admitList = [
{
facultyName: 'FSIT',
programName: 'BSc in CSE',
programTotalApplicant: 10
},
{
facultyName: 'FSIT',
programName: 'BSc in SWE',
programTotalApplicant: 5
},
{
facultyName: 'FSIT',
programName: 'BSc in EEE',
programTotalApplicant: 15
},
{
facultyName: 'FAHS',
programName: 'BSc in LLB',
programTotalApplicant: 10
},
{
facultyName: 'FAHS',
programName: 'BSc in English',
programTotalApplicant: 5
},
{
facultyName: 'FAHS',
programName: 'BSc in Pharmacy',
programTotalApplicant: 8
}
];
constructor() { }
ngOnInit() { }
мой HTML-файл:
<table class="table table-bordered">
<thead>
<tr>
<th>Faculty</th>
<th>Program</th>
<th>Program Total Applicant</th>
<th>Faculty Total</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let admit of admitList">
<td>{{admit.facultyName}}</td>
<td>{{admit.programName}}</td>
<td>{{admit.programTotalApplicant}}</td>
</tr>
</tbody>
</table>
Ответ №1:
Вот полное рабочее решение: РАБОЧАЯ ДЕМОНСТРАЦИЯ STACKBLITZ
component.ts
groupedFaculty;
ngOnInit() {
this.groupedFaculty = this.groupBy(this.admitList, 'shortName');
}
groupBy(objectArray, property) {
return objectArray.reduce(function (acc, obj) {
var key = obj[property];
if (!acc[key]) {
acc[key] = { count: 1, aggregation: obj.totalApplicant };
} else {
let count = acc[key].count 1;
let aggregation = acc[key].aggregation = obj.totalApplicant;
acc[key] = { count: count, aggregation: aggregation } ;
}
return acc;
}, {});
}
component.html
<table class="table table-bordered">
<thead>
<tr>
<th>Faculty</th>
<th>Program</th>
<th>Total Applicant</th>
<th>Faculty Total</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let admit of admitList; let i = index ">
<td>{{admit.shortName}}</td>
<td>{{admit.programName}}</td>
<td>{{admit.totalApplicant}}</td>
<td *ngIf="(admitList[i-1]?.shortName != admitList[i]?.shortName) || (i == 0)" [attr.rowspan]="this.groupedFaculty[admitList[i]?.shortName].count">
{{this.groupedFaculty[admitList[i]?.shortName]?.aggregation}}
</td>
</tr>
</tbody>
</table>
Комментарии:
1. спасибо за сотрудничество. Я нашел общий кандидат, но как отобразить в таблице в другой столбец
2. вау!! это сработало. большое спасибо. Вы сэкономили мне много времени.
Ответ №2:
Сначала создайте массив, сгруппированный по shortname
и вычислите общее количество, затем добавьте rowspan
атрибут на основе условия.
// HTML-код
<table class="table table-bordered">
<thead>
<tr>
<th>Faculty</th>
<th>Program</th>
<th>Total Applicant</th>
<th>Faculty Total</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let admit of admitList; let i = index">
<td>{{admit.shortName}}</td>
<td>{{admit.programName}}</td>
<td>{{admit.totalApplicant}}</td>
<td *ngIf="i==0 || admit.shortName !== admitList[i-1].shortName" [attr.rowspan] = "(groupbyShortName[admit.shortName].count) ? groupbyShortName[admit.shortName].count : 0">{{groupbyShortName[admit.shortName].sum}}</td>
</tr>
</tbody>
</table>
// Код компонента
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'ngbd-datepicker-popup',
templateUrl: './datepicker-popup.html'
})
export class NgbdDatepickerPopup implements OnInit {
groupbyShortName = {};
admitList = [
{
shortName: 'FSIT',
programName: 'BSc in CSE',
totalApplicant: 10
},
{
shortName: 'FSIT',
programName: 'BSc in SWE',
totalApplicant: 5
},
{
shortName: 'FSIT',
programName: 'BSc in EEE',
totalApplicant: 15
},
{
shortName: 'FAHS',
programName: 'BSc in LLB',
totalApplicant: 10
},
{
shortName: 'FAHS',
programName: 'BSc in English',
totalApplicant: 5
},
{
shortName: 'FAHS',
programName: 'BSc in Pharmacy',
totalApplicant: 8
}
];
constructor() {
this.groupbyShortName = this.admitList.reduce((accu, {shortName, totalApplicant, programName}) => {
if(!accu[shortName])
accu[shortName] = {count: 0, sum: 0, shortName, totalApplicant, programName};
accu[shortName].count = 1;
accu[shortName].sum = totalApplicant;
return accu;
}, {});
}
ngOnInit() { }
}
Ответ №3:
Самое простое решение — найти индекс вашего текущего элемента в сгруппированных строках:
import {Component, OnInit} from '@angular/core';
@Component({
selector: 'ngbd-datepicker-popup',
templateUrl: './datepicker-popup.html'
})
export class NgbdDatepickerPopup implements OnInit {
constructor() { }
ngOnInit() { }
rowspanBy(key: string){
return this.admitList.filter(ad => ad.shortName === key).length;
}
byIndex(admit: any){
const p1 = this.admitList.filter(ad => ad.shortName === admit.shortName);
return p1.indexOf(admit) === 0;
}
admitList = [
{
shortName: 'FSIT',
programName: 'BSc in CSE',
totalApplicant: 10
},
{
shortName: 'FSIT',
programName: 'BSc in SWE',
totalApplicant: 5
},
{
shortName: 'FSIT',
programName: 'BSc in EEE',
totalApplicant: 15
},
{
shortName: 'FAHS',
programName: 'BSc in LLB',
totalApplicant: 10
},
{
shortName: 'FAHS',
programName: 'BSc in English',
totalApplicant: 5
},
{
shortName: 'FAHS',
programName: 'BSc in Pharmacy',
totalApplicant: 8
}
];
}
<table class="table table-bordered">
<thead>
<tr>
<th>Faculty</th>
<th>Program</th>
<th>Total Applicant</th>
<th>Faculty Total</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let admit of admitList;">
<td>{{admit.shortName}}</td>
<td>{{admit.programName}}</td>
<td>{{admit.totalApplicant}}</td>
<td
[attr.rowspan]="rowspanBy(admit.shortName)"
*ngIf="byIndex(admit)"
>
{{rowspanBy(admit.shortName)}}
</td>
</tr>
</tbody>
</table>
Всего наилучшего
Комментарии:
1. Хорошее решение. Я уверен, что это работает, но разве это не общая рекомендация не использовать функции в представлениях html? что-то вроде чистого / неизменяемого / всегда согласованного состояния представления. В этом случае я не вижу проблемы. но в целом для обнаружения изменений.
2. вы правы, но также, в целом, я предпочитаю избегать заполнения шаблона длинными операторами, preferrig getter, strategy on push и ngxs state manager, всего наилучшего 😉
3. Мы согласны, что для решения чьей-то домашней задачи это было бы излишним 🙂