Как отобразить общее количество значений нескольких строк в отдельном столбце таблицы в angular 6?

#javascript #html #angular #html-table

#javascript #HTML #angular #html-таблица

Вопрос:

Я использую Angular 6 и html-таблицу. Я показал данные списка json в таблице. Я хочу показать общее количество абитуриентов с учетом факультета в отдельном столбце («Общее количество преподавателей»), но я не могу этого сделать. Пожалуйста, помогите мне решить эту проблему.

Я хочу сделать так: изображение

Ссылка на StackBlitz

мой 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:

Самое простое решение — найти индекс вашего текущего элемента в сгруппированных строках:

stackblitz

 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. Мы согласны, что для решения чьей-то домашней задачи это было бы излишним 🙂