计算可以从后端获取的 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)
})
}
我想计算这个 table 中 Amount 列的总和。使用 Node 和 MongoDB 从后端获取数据。我在此处附上了与 table 相关的大部分代码。
<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)
})
}