Home > Software design >  Cannot do ng for loop binding in angular 13
Cannot do ng for loop binding in angular 13

Time:10-11

I would like to do an angular 13 looping to split data to one column when duplicate entries came from database

now I got like this enter image description here

I Want like this

enter image description here

<table >
<thead>
<tr>
<td colspan="2">&nbsp;</td>
<th colspan="3" scope="colgroup" >{{'JobAllowanceperMonth.JobAllowanceperMonth' |
translate}}</th>
 </tr>
  <tr>
<th scope="col">{{ 'Organization.Organization' |
translate}}</th>
<th scope="col">{{ 'AttendancebenifitperDay.AttendancebenifitperDay' |
 translate}}</th>
 <th scope="col">{{ 'Step01.Step01' |
 translate}}</th>
 <th scope="col">{{ 'Step02.Step02' |
  translate}}</th>
 <th scope="col">{{ 'Step03.Step03' |
translate}}</th>                    
  </tr>
 </thead>
    <tbody *ngFor="let salaryVUGDetails of VUGSalaryDetails">
       <tr>
      <th scope="col">{{salaryVUGDetails.OrganisationName}}</th>
        <td>00,000</td>
         <td>{{salaryVUGDetails.Step1}}</td>
          <td>{{salaryVUGDetails.Step2}}</td>
        <td>{{salaryVUGDetails.Step3}}</td>
    </tr>
     </tbody>
  </table>

CodePudding user response:

You can also add a new property "rowspan" to your data to use in .html [attr.rowspan]. For this, first create a new array transform your original "VUGSalaryDetails" adding a new property rowspan

dataFormated = this.VUGSalaryDetails.map((x, i) => ({
    ...x,
    rowspan:
      i == 0 ||
      this.VUGSalaryDetails[i - 1].OrganizationName != x.OrganizationName
        ? this.VUGSalaryDetails.filter(
            (f) => f.OrganizationName == x.OrganizationName
          ).length
        : -1,
  }));

Then you can use some like

  <tbody>
    <tr *ngFor="let salaryVUGDetails of dataFormated">
      <td
        mat-cell
        *ngIf="salaryVUGDetails.rowspan != -1"
        [attr.rowspan]="
          salaryVUGDetails.rowspan > 0 ? salaryVUGDetails.rowspan : null
        "
      >
        {{ salaryVUGDetails.OrganizationName }}
      </td>
      <td>{{ salaryVUGDetails.Step1 }}</td>
      <td>{{ salaryVUGDetails.Step2 }}</td>
      <td>{{ salaryVUGDetails.Step3 }}</td>
    </tr>
  </tbody>

A stackblitz

CodePudding user response:

I see the demand for preprocessing your VUGSalaryDetails. I prefer to pipe over the Observables directy, but since your code seems to have the data stored in a variable directly, I work upon that in the controller. The following solution assumes, that each organization has exactly three steps:

// The final datastructure will be a hashmap pointing the organizationName as a key to an array of {step1,step2,step3} entries: 
public processedData: Map<string, {
    Step1: number,
    Step2: number,
    Step3: number
}[]> = new Map<string, {
    Step1: number,
    Step2: number,
    Step3: number
}[]>; 


let VUGSalaryDetails = [
    { 
        "OrganizationName": "Organization Level",
        "Step1": "4900",
        "Step2": "5400",
        "Step3": "5600" },
    { 
        "OrganizationName": "Organization Level",
        "Step1": "18826",
        "Step2": "18926",
        "Step3": "19026" },
    ...
]; // example data to work with.

// now we loop through the originalData and add them to the hashmap:
for (let i = 0; i < VUGSalaryDetails.length; i  ) {
    // if the hashmap has no entry yet for the current organizationName, then set it:
    if (!this.processedData.has(VUGSalaryDetails[i].OrganizationName) {
        this.processedData.set(VUGSalaryDetails[i].OrganizationName, [{
            Step1: VUGSalaryDetails[i].Step1,
            Step2: VUGSalaryDetails[i].Step2,
            Step3: VUGSalaryDetails[i].Step3
        }]);
    } else {
        // otherwise, add it to the current entry:
        let previousEntry = this.processedData.get(VUGSalaryDetails[i].OrganizationName);
        previousEntry.add({
            Step1: VUGSalaryDetails[i].Step1,
            Step2: VUGSalaryDetails[i].Step2,
            Step3: VUGSalaryDetails[i].Step3
        });
        this.processedData.set(VUGSalaryDetails[i].OrganizationName, previousEntry);
    }
};

Now we have the processedData hashmap, over which we can loop in the html body with the keyvalue pipe:

<tbody *ngFor="let salaryVUGDetails of processedData | keyvalue">
    <tr>
        <th scope="col">{{salaryVUGDetails.key}}</th> <!-- the key is the organizationName -->
        <td>00,000</td>
        <td> <!-- first td are the rows of Step1's -->
            <p *ngFor="let row of salaryVUGDetails.value">{{row.Step1}<br></p>
        </td>
        <td> <!-- 2nd td are the rows of Step2's -->
            <p *ngFor="let row of salaryVUGDetails.value">{{row.Step2}<br></p>
        </td>
        <td> <!-- 3rd td are the rows of Step3's -->
            <p *ngFor="let row of salaryVUGDetails.value">{{row.Step3}<br></p>
        </td>
    </tr>
</tbody>

Now we probably need to add some css to make everything aligned good looking.

  • Related