简体   繁体   中英

mat-table with multiple footers

I would like to create the following: a table with some extra footer rows that are not tied specifically to the dataSource of the mat-table , but to some other dataSource that is also in the component. I should specify I do not require them to be multiple footers ( as I can't find good ways for this to be possible), but I just need these last 3 to be responsive.

预期结果图像

Our data model looks like this:

{
   // These contain the info for the last 3 rows (netto bedrag, BTW, Totaalbedrag)
   netAmount: number;
   vatAmount: number; 
   totalAmount: number;
   lines: // lines is our data source
   [
     {
        // These are the columns (Omschrijving, Tarief, Aantal, totaal)
        description: string;
        unitPrice: number;
        quantity: number;
        total: number;
     }
   ];
}

Our HTML looks like this, I have omitted CSS for readability but I do require the dividers!

<div class="purchase-invoices__lines">
  <mat-table #table [dataSource]="dataSource">
    <ng-container matColumnDef="description">
      <mat-header-cell *matHeaderCellDef>Omschrijving</mat-header-cell>
      <mat-cell *matCellDef="let invoiceLine">
        <span class="mobile-label">Omschrijving:</span>
        <span class="mobile-value"> {{ invoiceLine.description }} </span>
      </mat-cell>
      <mat-footer-cell *matFooterCellDef>
        <span class="mobile-value net-amount_text ">
          Netto Bedrag
        </span>
      </mat-footer-cell>
    </ng-container>

    <ng-container matColumnDef="tariff">
      <mat-header-cell *matHeaderCellDef>Tarief</mat-header-cell>
      <mat-cell *matCellDef="let invoiceLine">
        <span class="mobile-label">Tarief:</span>
        <span class="mobile-value"> {{ invoiceLine.unitPrice | currency: 'EUR' }}</span> </mat-cell
      ><mat-footer-cell *matFooterCellDef></mat-footer-cell>
    </ng-container>

    <ng-container matColumnDef="amount">
      <mat-header-cell *matHeaderCellDef>Aantal</mat-header-cell>
      <mat-cell *matCellDef="let invoiceLine">
        <span class="mobile-label">Aantal:</span>
        <span class="mobile-value"> {{ invoiceLine.quantity }}</span>
      </mat-cell>
      <mat-footer-cell *matFooterCellDef></mat-footer-cell>
    </ng-container>

    <ng-container matColumnDef="total">
      <mat-header-cell *matHeaderCellDef>Totaal</mat-header-cell>
      <mat-cell *matCellDef="let invoiceLine">
        <span class="mobile-label">Totaal:</span>
        <span class="mobile-value"> {{ invoiceLine.totalPrice | currency: 'EUR' }}</span>
      </mat-cell>
      <mat-footer-cell *matFooterCellDef>
        <span class="mobile-value"> {{ purchaseInvoice.netAmount | currency: 'EUR' }} </span>
      </mat-footer-cell>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
    <mat-footer-row *matFooterRowDef="displayedColumns"></mat-footer-row>
  </mat-table>
</div>

My result so far looks like this:

当前结果

Do you guys know how I would create my expected result? As you can read in the title, my first thought was to have multiple footers but I do not know if this is possible. I have found this example but I can't get it to work like in my example.

I am a back-ender myself and can't create a great example or explain why things do not work, so I pray you guys can magically solve my issue.

Thank you so much!

The way I fixed it:

In the TS:

  displayedColumns = ['description', 'tariff', 'amount', 'total'];
  displayedVatColumns = ['vatAmountTitle', 'emptyFooter', 'emptyFooter', 'vatAmount'];
  displayedTotalColumns = ['totalAmountTitle', 'emptyFooter', 'emptyFooter', 'totalAmount'];

In the HTML:

<div class="purchase-invoices__lines">
  <mat-table #table [dataSource]="purchaseInvoice.invoiceLines">
    <ng-container matColumnDef="description">
      <mat-header-cell *matHeaderCellDef>Omschrijving</mat-header-cell>
      <mat-cell *matCellDef="let invoiceLine">
        <span class="mobile-label">Omschrijving:</span>
        <span class="mobile-value"> {{ invoiceLine.description }} </span>
      </mat-cell>
      <mat-footer-cell *matFooterCellDef class="bold mobile-hide"><span class="mobile-value">Netto Bedrag</span></mat-footer-cell>
    </ng-container>

    <ng-container matColumnDef="tariff">
      <mat-header-cell *matHeaderCellDef>Tarief</mat-header-cell>
      <mat-cell *matCellDef="let invoiceLine">
        <span class="mobile-label">Tarief:</span>
        <span class="mobile-value"> {{ invoiceLine.unitPrice | currency: 'EUR' }}</span>
      </mat-cell>
      <mat-footer-cell *matFooterCellDef class="mobile-hide"></mat-footer-cell>
    </ng-container>

    <ng-container matColumnDef="amount">
      <mat-header-cell *matHeaderCellDef>Aantal</mat-header-cell>
      <mat-cell *matCellDef="let invoiceLine">
        <span class="mobile-label">Aantal:</span>
        <span class="mobile-value"> {{ invoiceLine.quantity }}</span>
      </mat-cell>
      <mat-footer-cell *matFooterCellDef class="mobile-hide"></mat-footer-cell>
    </ng-container>

    <ng-container matColumnDef="total">
      <mat-header-cell *matHeaderCellDef>Totaal</mat-header-cell>
      <mat-cell *matCellDef="let invoiceLine">
        <span class="mobile-label">Totaal:</span>
        <span class="mobile-value"> {{ invoiceLine.netPrice | currency: 'EUR' }}</span>
      </mat-cell>
      <mat-footer-cell *matFooterCellDef>
        <span class="mobile-label bold">Netto Bedrag</span>
        <span class="mobile-value bold"> {{ purchaseInvoice.netAmount | currency: 'EUR' }}</span>
      </mat-footer-cell>
    </ng-container>

    <!-- empty footer row-->
    <ng-container matColumnDef="emptyFooter">
      <mat-footer-cell *matFooterCellDef class="mobile-hide"></mat-footer-cell>
    </ng-container>

    <!-- set footer for vat amount-->
    <ng-container matColumnDef="vatAmountTitle">
      <mat-footer-cell *matFooterCellDef class="mobile-hide">BTW (21%)</mat-footer-cell>
    </ng-container>

    <ng-container matColumnDef="vatAmount">
      <mat-footer-cell *matFooterCellDef>
        <span class="mobile-label">BTW (21%)</span>
        <span class="mobile-value"> {{ purchaseInvoice.vatAmount | currency: 'EUR' }}</span>
      </mat-footer-cell>
    </ng-container>

    <!-- set footer for total amount-->
    <ng-container matColumnDef="totalAmountTitle">
      <mat-footer-cell *matFooterCellDef class="mobile-hide bold">Totaalbedrag</mat-footer-cell>
    </ng-container>

    <ng-container matColumnDef="totalAmount">
      <mat-footer-cell *matFooterCellDef>
        <span class="mobile-label bold">Totaalbedrag</span>
        <span class="mobile-value bold"> {{ purchaseInvoice.totalAmount | currency: 'EUR' }}</span>
      </mat-footer-cell>
    </ng-container>

    <mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
    <mat-row *matRowDef="let row; columns: displayedColumns"></mat-row>
    <mat-footer-row *matFooterRowDef="displayedColumns" class="nettoRow"></mat-footer-row>
    <mat-footer-row *matFooterRowDef="displayedVatColumns" class="vatRow"></mat-footer-row>
    <mat-footer-row *matFooterRowDef="displayedTotalColumns" class="totalRow"></mat-footer-row>
  </mat-table>
</div>

I hope this helps people!

Ok, let me give this one a go. I was looking for a solution to have my paginator within the table and came across your issue. So, I'm not sure if this is the best solution but it can work. If you don't need the footers to reference those columns (or even if you do but want multiple footers), you can add multiple ng-containers just for your footers. Similar to the example you could have

  <ng-container matColumnDef="netto">
    <td mat-footer-cell *matFooterCellDef>
      Netto Bedrag
    </td>
  </ng-container>

  <ng-container matColumnDef="blankCell">
    <td mat-footer-cell *matFooterCellDef>
    </td>
  </ng-container>

  <ng-container matColumnDef="total">
    <td mat-footer-cell *matFooterCellDef>
     {{ purchaseInvoice.netAmount | currency: 'EUR' }}
    </td>
  </ng-container>

And then at the bottom you create a new mat-footer-row with these new cells. You can reuse the blankCell as many times as you need.

<tr mat-footer-row
  *matFooterRowDef="['netto', 'blankCell', 'blankCell', 'total']; sticky: true">
</tr>

Just repeat for each footer you need (reusing the blankCell for any blank cells you need). The order will be based on your array of matColumnDef names. Since you already have the one for Netto Bedrag, you can skip that and replace it with the ones you need (BTW and Totaalbedrag). There's probably a cleaner solution but this will at least get you close.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM