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

标签 angular angular-material-table

我想计算此表中“金额”列的总和。使用 Node 和 MongoDB 从后端获取数据。我在这里附上了与该表相关的大部分代码。

enter image description here 这是我的 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)
 })
}

关于angular - 计算可从后端获取的 Angular Material Table 列中的数据总和,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65198783/

相关文章:

angular - 如何在将图像上传到服务器之前以 Angular 2 调整图像大小?

css - Angular 垫表 : Is it possible to merge cells by columns?

Angular Material Table - 如何更新现有表格的列标题?

node.js - "ng new xxx"给出错误错误代码-4048

Angular Material 分页未显示但正在运行

angular - 对 Angular Material 表进行排序时,您可以在不修改数据的情况下查看数据吗?

angular - 当组件更新值时,指令@Input 变量没有得到更新

typescript - Angular2 访问全局服务而不将其包含在每个构造函数中

angular - 使用管道获取 Angular 中字符串的第一个单词?