Search code examples
htmlangularrenderingngforangular-ng-if

How to stop rendering of an item if it has already been iterated - ngFor, ngIf, Angular 16


I have an array of objects which i have to iterate through and present some data (rafale and quantities of raw, semi-finished and finished parts) in the table.

My array of objects is as follows:

tableMongoData = [
    {
      ref: '322416730R',
      type: 'RAW',
      rafale: [
        {
          name: '14x63',
          refs: [
            {
              type: 'PB',
              ref: '8201729087',
              partQty: '1.502',
              rowspan: 1,
            },
            {
              type: 'PN',
              ref: '8201729088',
              partQty: '921',
              rowspan: 1,
            },
            {
              type: 'PA',
              ref: '322419484R',
              partQty: '112',
              rowspan: 1,
            },
          ],
        },
        {
          name: '14x69',
          refs: [
            {
              type: 'PB',
              ref: '8201729081',
              partQty: '761',
              rowspan: 1,
            },
            {
              type: 'PN',
              ref: '8201729083',
              partQty: '295',
              rowspan: 1,
            },
            {
              type: 'PA',
              ref: '322410929R',
              partQty: '868',
              rowspan: 1,
            },
          ],
        },
      ],
      partQty: '1.467',
      rowspan: 2,
    },
    {
      ref: '322419487R',
      type: 'RAW',
      rafale: [
        {
          name: '15x58',
          refs: [
            {
              type: 'PB',
              ref: '8201729084',
              partQty: '2.977',
              rowspan: 1,
            },
            {
              type: 'PN',
              ref: '8201729085',
              partQty: '2.627',
              rowspan: 1,
            },
            {
              type: 'PA',
              ref: '322414657R',
              partQty: '397',
              rowspan: 1,
            },
          ],
        },
      ],
      partQty: '7.555',
      rowspan: 1,
    },
  ];

My HTML file is as follows:

<div class="container">
  <table class="table table-responsive mt-5 caption-top">
    <caption></caption>
    <thead class="align-middle table-group-divider">
      <tr>
        <th class="text-center" scope="col">IDENTIFICAÇÃO PEÇA</th>
        <th class="text-center" scope="col">PEÇA EM BRUTO</th>
        <th class="text-center" scope="col">PEÇA BRANCA</th>
        <th class="text-center" scope="col">PEÇA NEGRA</th>
        <th class="text-center" scope="col">PEÇA ACABADA</th>
      </tr>
    </thead>
    <tbody class="table-group-divider">
      <ng-container *ngFor="let refRaw of tableMongoData">
        <tr *ngFor="let rafale of refRaw.rafale">
          <th class="text-center" scope="row">{{ rafale.name }}</th>
          <td
            [attr.rowspan]="refRaw.rowspan"
            class="text-center align-middle"
            tabindex="0"
            data-html="true"
            data-bs-toggle="tooltip"
            data-bs-placement="top"
            data-bs-title="Referência: "
          >
            {{ refRaw.partQty }}
          </td>
        </tr>
      </ng-container>
    </tbody>
  </table>
</div>

My problem is that the quantity of the first RAW reference is rendered twice (picture TABLE).

I think it has to do with the fact that in my *ngFor inside a i iterate through 3 rafale references, thus a inside that is rendered 3 times.

Is there any way of stopping iteration knowing that the first reference has already been iterated and its quantity has already been rendered?

Working example in

I've already tried to use *ngIf in order to check whether the reference has already been iterated, and trackBy functionality but without success. There must be something wrong with the way i implement the code.


Solution

  • Solution was inspired by the comment of Prabath Udayanga.

    If I'm able to define whether I want to print a value or not, using *ngIf directive, I should be able, using *ngIf directive, to tell the table when to create a data cell.

    I made the following modification to code:

    <tbody class="table-group-divider">
            <ng-container *ngFor="let refRaw of tableMongoData">
                <tr *ngFor="let rafale of refRaw.rafale; let i = index">
                    <th class="text-center" scope="row">{{ rafale.name }}</th>
                    <td *ngIf="i === 0" [attr.rowspan]="refRaw.rowspan" class="text-center align-middle" tabindex="0"
                        data-html="true" data-bs-toggle="tooltip" data-bs-placement="top" data-bs-title="Referência: ">
                        {{ refRaw.partQty }}</td>
                    <td *ngFor="let ref of rafale.refs" [attr.rowspan]="ref.rowspan" class="text-center align-middle"
                        tabindex="0" data-html="true" data-bs-toggle="tooltip" data-bs-placement="top"
                        data-bs-title="Referência: ">
                        {{ ref.partQty }}
                    </td>
                </tr>
            </ng-container>
        </tbody>
    

    In tag I've added a condition based on an index of rafale: *ngIf="i === 0". This means that the cell data is created only for the first instance of the rafale. Since I always have at least 1 rafale identifiction, I always create a cell data for an existing rafale. When I have multiple rafales per part reference, I create only one cell data and rowspan attribute takes care of the rest.

    Working code is on the following link: Working code