0

I am using Angular 6 and html table. I have shown a json list data in to table. I want to show faculty wise total program applicant in to separate column ('Faculty Total') but i can't able to do this. Please guide me to solve this problem.

I want to do like this: image

StackBlitz Link

my ts file:

 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() { }

my html file:

 <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>

3 Answers 3

3

Here's a full working solution: WORKING STACKBLITZ DEMO

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>
Sign up to request clarification or add additional context in comments.

2 Comments

thanks for your co-operation. I have found faculty wise total applicant but how to show in table in to another column
waoo!! it's worked. thanks a lot. You saved my lot of time.
2

First create a array grouped by shortname and calculate total then add rowspan attribute based on condition.

// HTML code

 <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>

// Component code

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() { }

}

Comments

2

The simplest solution is to find the index of your current item in the grouped rows:

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>

All the best

3 Comments

Nice solution. I'm sure it works, but isn't it a general recommendation not to use functions in html views? something like clean / immutable / always consistent view state. In this case I don't see a problem. but in general for change detection.
you are right, but also, in general I prefer to avoid to fill the template with long statements, preferrig getter, strategy on push and ngxs state manager, all the best ;)
We agree, that for solving someone's homework task, this would be overkill :)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.