计算可以从后端获取的 Angular Material Table 列中的数据总和

Calculate sum of data in an Angular Material Table column that can be fetched from back-end

我想计算这个 table 中 Amount 列的总和。使用 Node 和 MongoDB 从后端获取数据。我在此处附上了与 table 相关的大部分代码。

这是我的 table.component.html

<div class="table">

    <div class="spinner-container" *ngIf="dataSource.loading$ | async">
        <mat-spinner></mat-spinner>
    </div>

    <mat-table class="the-table mat-elevation-z8" [dataSource]="dataSource">
        <ng-container matColumnDef="item">
            <mat-header-cell *matHeaderCellDef>Item</mat-header-cell>
            <mat-cell *matCellDef="let row">{{row.item}}</mat-cell>
            <mat-footer-cell *matFooterCellDef></mat-footer-cell>
        </ng-container>

        <ng-container matColumnDef="rate">
            <mat-header-cell *matHeaderCellDef>Item Rate</mat-header-cell>
            <mat-cell *matCellDef="let row">{{row.rate}}</mat-cell>
            <mat-footer-cell *matFooterCellDef></mat-footer-cell>
        </ng-container>

        <ng-container matColumnDef="quantity">
            <mat-header-cell *matHeaderCellDef>Quantity</mat-header-cell>
            <mat-cell *matCellDef="let row">{{row.quantity}}</mat-cell>
            <mat-footer-cell *matFooterCellDef>Total Amount: </mat-footer-cell>
        </ng-container>

        <ng-container matColumnDef="amount">
            <mat-header-cell *matHeaderCellDef>Amount</mat-header-cell>
            <mat-cell *matCellDef="let row">{{row.amount}}</mat-cell>
            <mat-footer-cell *matFooterCellDef>{{ calculateTotal() }}</mat-footer-cell>
        </ng-container>

        <ng-container matColumnDef="action">
            <mat-header-cell *matHeaderCellDef>Action</mat-header-cell>
            <mat-cell *matCellDef="let row">
                <button mat-button color="warn" (click)="onDelete(row.id)">DELETE</button>
            </mat-cell>
            <mat-footer-cell *matFooterCellDef></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 class="sticky-footer" *matFooterRowDef="displayedColumns"></mat-footer-row>
    </mat-table>
</div>

这是我的table.component.ts

import { Component, OnInit } from "@angular/core";
import { Line } from '../../model/line.model';
import { BodyService } from '../../services/body.service';
import { TableDataSource } from './../../services/table.datasource';

@Component({
    selector: 'app-table',
    templateUrl: './table.component.html',
    styleUrls: ['./table.component.css']
})
export class TableComponent implements OnInit {
    line: Line;

    dataSource: TableDataSource;

    displayedColumns = [
        'item',
        'rate',
        'quantity',
        'amount',
        'action'
    ];

    constructor(private bodyService: BodyService) { }

    ngOnInit() {
        this.bodyService.getLines();
        this.dataSource = new TableDataSource(this.bodyService);
        this.dataSource.loadTable();
    }

    onDelete(lineId: string) {
        console.log(lineId);
        this.bodyService.deleteLine(lineId);
    }

    calculateTotal() {
        return "Sum";
    }
}

这是我的table.datasource.ts

import { CollectionViewer, DataSource } from '@angular/cdk/collections';
import { Observable, BehaviorSubject, of } from 'rxjs';
import { catchError, finalize } from "rxjs/operators";
import { Line } from '../model/line.model';
import { BodyService } from './body.service';

export class TableDataSource implements DataSource<Line> {

    private linesSubject = new BehaviorSubject<Line[]>([]);

    private loadingSubject = new BehaviorSubject<boolean>(false);

    public loading$ = this.loadingSubject.asObservable();

    constructor(private bodyService: BodyService) { }

    loadTable() {
        this.loadingSubject.next(true);

        this.bodyService.getLines();

        this.bodyService.getLineUpdateListener().pipe(
            catchError(() => of([])),
            finalize(() => this.loadingSubject.next(false))
        ).subscribe(lines => {
            this.linesSubject.next(lines);
        });
    }

    connect(collectionViewer: CollectionViewer): Observable<Line[]> {
        console.log('Connecting data source');
        return this.linesSubject.asObservable();
    }

    disconnect(collectionViewer: CollectionViewer): void {
        this.linesSubject.complete();
        this.loadingSubject.complete();
    }
}

这是我的body.service.ts

import { Injectable } from "@angular/core";
import { HttpClient } from '@angular/common/http';
import { Subject } from 'rxjs';
import { map } from 'rxjs/operators';

import { Line } from './../model/line.model';

const BACKEND_URL = "http://localhost:3000/api/lines";

@Injectable({ providedIn: 'root' })
export class BodyService {
    private lines: Line[] = [];
    private linesUpdated = new Subject<Line[]>();

    constructor(private http: HttpClient) { }

    getLines() {
        this.http.get<{ message: string, lines: any }>(BACKEND_URL)
            .pipe(map(lineData => {
                return lineData.lines.map(line => {
                    return {
                        item: line.item,
                        rate: line.rate,
                        quantity: line.quantity,
                        amount: line.amount,
                        id: line._id
                    }
                })
            })).subscribe(transformedLines => {
                this.lines = transformedLines;
                this.linesUpdated.next([...this.lines]);
            });
    }

    getLineUpdateListener() {
        return this.linesUpdated.asObservable();
    }

    addLine(item: string, rate: number, quantity: number) {
        const line: Line = { id: null, item: item, rate: rate, quantity: quantity, amount: rate * quantity };
        this.http.post<{ message: string, lineId: string }>(BACKEND_URL, line)
            .subscribe(responseData => {
                const id = responseData.lineId;
                line.id = id;
                this.lines.push(line);
                this.linesUpdated.next([...this.lines]);
            });
    }

    deleteLine(lineId: string) {
        this.http.delete(BACKEND_URL + "/" + lineId)
            .subscribe(() => {
                const updatedLines = this.lines.filter(line => line.id !== lineId);
                this.lines = updatedLines;
                this.linesUpdated.next([...this.lines])
            });
    }
}

首先您需要在 TableDataSource 上创建可用的行;

getLines(){
  return this.linesSubject
}

然后在你的 calculateTotal 方法中

calculateTotal(){
   this.dataSource.getLines().subscribe(lines => {
   this.totalAmount = lines.reduce((total,line) => total + line.amount ,0)
 })
}