Вычислить сумму данных в столбце таблицы угловых материалов, которые могут быть извлечены из серверной части

#node.js #angular #angular-material-table

#angular #angular-material-table

Вопрос:

Я хочу вычислить сумму столбца Amount в этой таблице. Данные извлекаются из серверной части с помощью Node и MongoDB. Я приложил большую часть кода, относящегося к таблице, здесь.

введите описание изображения здесь Это мой 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";
    }
}
 

Это моя таблица.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])
            });
    }
}
 

Ответ №1:

Сначала вам нужно создать доступные строки в TableDataSource;

 getLines(){
  return this.linesSubject
}
 

затем в вашем методе calculateTotal

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

Комментарии:

1. Спасибо, тогда как я могу отобразить результат в HTML-файле?

2. {{ TotalAmount }} но сначала создайте TotalAmount prop в вашем компоненте