将数据从 mat-table 传递到同一组件中的 mat-card

passing data from mat-table to mat-card in same component

我有一个带有 mat-table 的组件,我可以在 html 文件中使用我的数据源中的变量。我的 table 有一个扩展面板,可以打开一张垫卡。我还需要从用于数据源的相同 class 传递参数。虽然我可以很容易地访问参数,但我希望按特定字段过滤它们,但我不知道该怎么做。我知道Angular,建议使用管道进行过滤;但是,我不知道如何传递这个特定字段以便我可以应用过滤器。基本上,我希望数据按 this.jobUuid 过滤。我已经尝试了几种不同的 if 语句,但它不起作用。虽然我可以轻松创建管道,但如何将 this.jobUuid 传递给管道。我希望我的问题很清楚。下面是我的代码。 html

<div class="container-fluid">
  <form>
    <mat-form-field color="warn" class="input2">
      <input matInput [max]="maxDate" [matDatepicker]="picker" placeholder="Choose a date" [(ngModel)]="dateValue"
             [ngModelOptions]="{standalone: true}" (dateChange)="callJobService(dateValue)">
      <mat-datepicker-toggle matSuffix [for]="picker"></mat-datepicker-toggle>
      <mat-datepicker #picker></mat-datepicker>
    </mat-form-field>

    <div class="input1">
      <button class="btn btn-danger btn-lg" (click)="refreshDate()">
        <span class="glyphicon glyphicon-refresh"></span>Refresh
      </button>
    </div>
    <div class="input1">
      <mat-form-field color="warn" appearance="legacy">
        <input matInput (keyup)="applyFilter($event.target.value)" placeholder="Filter">
      </mat-form-field>
    </div>
  </form>
  <div class="report-container mat-elevation-z8">
    <mat-table #table [dataSource]="dataSource" matSort>
      <ng-container matColumnDef="processStatus">
        <mat-header-cell class=col1 *matHeaderCellDef mat-sort-header>Status</mat-header-cell>
        <mat-cell class=col1 *matCellDef="let job">{{job.processStatus}}</mat-cell>
      </ng-container>
      <ng-container matColumnDef="startTime">
        <mat-header-cell class=col2 *matHeaderCellDef mat-sort-header>Start Time</mat-header-cell>
        <mat-cell class=col2 *matCellDef="let job">{{job.startTime| date :'medium'}}</mat-cell>
      </ng-container>
      <ng-container matColumnDef="endTime">
        <mat-header-cell class=col3 *matHeaderCellDef mat-sort-header>End Time</mat-header-cell>
        <mat-cell class=col3 *matCellDef="let job">{{job.endTime| date :'medium'}}</mat-cell>
      </ng-container>
      <ng-container matColumnDef="numberOfReports">
        <mat-header-cell class=col4 *matHeaderCellDef mat-sort-header>Number of Reports</mat-header-cell>
        <mat-cell class=col4 *matCellDef="let job">{{job.reportCount}}</mat-cell>
      </ng-container>
      <ng-container matColumnDef="numberOfBatches">
        <mat-header-cell class=col5 *matHeaderCellDef mat-sort-header>Number of Batches</mat-header-cell>
        <mat-cell class=col5 *matCellDef="let job">{{job.batchCount}}</mat-cell>
      </ng-container>
      <ng-container class=col6 matColumnDef="addArrow">
        <mat-header-cell *matHeaderCellDef></mat-header-cell>
        <mat-cell *matCellDef="let job">
          <mat-icon (click)="expandedElement = expandedElement === job ? null : job">expand_more</mat-icon>
        </mat-cell>
      </ng-container>
      <ng-template #tpl let-job>
        <div class="mat-row detail-row" [@detailExpand] style="overflow: hidden">
          <mat-card class="card1">
            <mat-card-title>Input -> Batches</mat-card-title>
            <mat-card-header>
              <mat-card-actions>
                <button class="btn btn-danger btn-lg" mat-raised-button (click)="collapsed=false">Show batch details</button>
                <button class="btn btn-dark btn-lg" mat-raised-button (click)="collapsed=true">Hide batch details</button>
              </mat-card-actions>
            </mat-card-header>
            <mat-card-content *ngIf="!collapsed">
              <div *ngFor="let job of jobs">
                <div *ngFor="let batchList of job.batchList let jobUuid = index">
                  <p class="title"><b>Batch ID:</b> {{batchList.batchId}}</p>
                  <p class="title"><b>Event Type:</b> {{batchList.eventType}}</p>
                  <p class="title"><b>Data Path:</b> {{batchList.dataPath}}</p>
                  <br>
                </div>
              </div>
            </mat-card-content>
            <br>
          </mat-card>
          <mat-card class="card1">
            <mat-card-title>Output -> Reports</mat-card-title>
            <mat-card-header>
              <mat-card-actions>
                <button class="btn btn-danger btn-lg" mat-raised-button (click)="collapsed2=false">Show report details</button>
                <button class="btn btn-dark btn-lg" mat-raised-button (click)="collapsed2=true">Hide report details</button>
              </mat-card-actions>
            </mat-card-header>
            <mat-card-content *ngIf="!collapsed2">
              <div *ngFor="let job of jobs">
                  <div *ngFor="let reportList of filterByVariable(job, jobUuid">
                    <p class="title"><b>Transfer Status:</b> {{reportList.transferStatus}}</p>
                  <p class="title"><b>File Size:</b> {{reportList.fileSize}}</p>
                  <p class="title"><b>Last Updated:</b> {{reportList.lastUpdate | date :'medium'}}</p>
                  <p class="title"><b>ADLS Full Path:</b> {{reportList.adlsPath}}</p>
                  <!--                  <br>-->
                  <button class="button-download" class="btn btn-light btn-lg" (click)="downloadFile(reportList.adlsPath)">Download File
                  </button>
                  <br><br>
<!--                  </div>-->
                </div>
              </div>
            </mat-card-content>
            <br>
          </mat-card>
        </div>
      </ng-template>
      <mat-header-row *matHeaderRowDef="displayedReportsColumn"></mat-header-row>
      <mat-row *matRowDef="let row; columns: displayedReportsColumn;" matRipple
               class="element-row" [cdkDetailRow]="row"
               [cdkDetailRowTpl]="tpl">
      </mat-row>
    </mat-table>
  </div>
</div>

组件

import {animate, state, style, transition, trigger} from '@angular/animations';
import {Component, OnInit, ViewChild} from '@angular/core';
import {MatSort} from "@angular/material/sort";
import {from} from 'rxjs';
import {DownloadFileService} from "../../services/download-file.service";
import {DatePipe} from '@angular/common';
import {MatTableDataSource} from "@angular/material/table";
import {saveAs} from 'file-saver';
import {JobService} from "../../services/job.service";
import {Job} from "../../models/Job";
import {BatchList} from "../../models/batchList";
import {ReportList} from "../../models/reportList";

@Component({
  selector: 'app-report-output',
  templateUrl: './jobs.component.html',
  styleUrls: ['./jobs.component.scss'],
  animations: [
    trigger('detailExpand', [
      state('void', style({height: '0px', minHeight: '0', visibility: 'hidden'})),
      state('*', style({height: '*', visibility: 'visible'})),
      transition('void <=> *', animate('225ms cubic-bezier(0.4, 0.0, 0.2, 1)'))
    ])
  ],
})
export class JobsComponent implements OnInit {

  jobs: Job[];
  // batchLists: BatchList[];
  // reportLists: ReportList[];
  dateValue = new Date();
  maxDate = new Date();
  dataSource: MatTableDataSource<Job>;
  expandedElement: Job | null;
  collapsed = true;
  collapsed2 = true;
  displayedReportsColumn: string[] = ['processStatus', 'startTime', 'endTime', 'numberOfReports', 'numberOfBatches', 'addArrow'];

  @ViewChild(MatSort) sort: MatSort;

  isExpansionDetailRow = (index, row) => row.hasOwnProperty('detailRow');



  constructor(private jobService: JobService, private downloadFileService: DownloadFileService, private datePipe: DatePipe) {
  }

  ngOnInit() {
    this.callJobService(new Date());
  }

  callJobService(value: Date) {
    this.jobService.mergeReportJob(value)
      .subscribe(res => {
        this.jobs = <Job[]><unknown>res;
        // console.log(JSON.stringify(this.jobs));
        this.dataSource = new MatTableDataSource(this.jobs);
        // this.dataSource.paginator = this.paginator;
        this.dataSource.sort = this.sort;
      });
  }

  applyFilter(filterValue: string) {
    filterValue = filterValue.trim(); // Remove whitespace
    filterValue = filterValue.toLowerCase(); // Datasource defaults to lowercase matches
    this.dataSource.filterPredicate = (data: any, filter) => {
      const dataStr = JSON.stringify(data).toLowerCase();
      return dataStr.indexOf(filter) != -1;
    }
    this.dataSource.filter = filterValue;
  }

filterbyVariable(job: Job, jobUuid: string) {
return job. reportList.filter(r=> r.Uuid == jobUuid)


  refreshDate() {
    this.callJobService(this.dateValue);
  }

  downloadFile(pathToDownload) {
    console.log(pathToDownload);
    from(this.downloadFileService.downloadFile({'pathToDownload': pathToDownload}))
      .subscribe((data: any) => {
        saveAs(new Blob([data], {type: 'application/octet-stream'}), (pathToDownload.substring(pathToDownload.indexOf('part'))));
      })
  }
}

服务文件

import {Injectable} from '@angular/core';
import {HttpClient} from "@angular/common/http";
import {AppConfig} from "../app.config";
import {DatePipe} from "@angular/common";
import {Job} from "../models/Job";

@Injectable({
  providedIn: 'root'
})
export class JobService {
  private apiUrl = '';
  private jobsEndPoint = '';


  constructor(private http: HttpClient, private appConfig: AppConfig, public datePipe: DatePipe) {
    this.apiUrl = this.appConfig.settings.apiServer.apiUrl;
    this.jobsEndPoint = this.appConfig.settings.apiServer.jobsEndPoint;
  }

  mergeReportJob(date: Date) {
    const transfomedDate = this.datePipe.transform(date, 'yyyyMMdd');
    const body = `date = ${date}`;
    return this.http.post<Job[]>(`${this.apiUrl}${this.jobsEndPoint}?date=${transfomedDate}`, body)

  }

}

class 文件

import {ReportList} from "./reportList";

export class Job {
  jobUuid: string;
  businessDate: string;
  dataSource: string;
  eventType: string;
  reportName: string;
  processStatus: string;
  startTime: string;
  endTime: string;
  batchCount: number;
  reportCount: number;
  batchList: BatchList[];
  reportList: ReportList[];
}

如果我猜对了(我可能猜错了),您想将显示的 reportList 项目过滤为包含 jobUuid 的项目。

如果是这样,您可以使用一个函数来过滤 *ngFor 中的数据。

Quick StackBlitz demo.

<mat-card-content *ngIf="!collapsed2">
              <div *ngFor="let job of jobs; let jobUuid = index">
                  <div *ngFor="let reportList of filteredReports(jobUuid)">
<!--                    <div *ngIf="reportList.jobUuid==jobUuid">-->
                    <p class="title"><b>Transfer Status:</b> {{reportList.transferStatus}}</p>
                  <p class="title"><b>File Size:</b> {{reportList.fileSize}}</p>
                  <p class="title"><b>Last Updated:</b> {{reportList.lastUpdate | date :'medium'}}</p>
                  <p class="title"><b>ADLS Full Path:</b> {{reportList.adlsPath}}</p>
                  <!--                  <br>-->
                  <button class="button-download" class="btn btn-light btn-lg" (click)="downloadFile(reportList.adlsPath)">Download File
                  </button>
                  <br><br>
<!--                  </div>-->
                </div>
              </div>
            </mat-card-content>

ts:

 filteredReports(id)
{
    return this.jobs.find(j => j.jobUuid == id).reportList.filter(r => r.jobUuid == id);
}

或者将作业传递给函数以直接对该作业进行过滤,以及您需要的任何其他内容取决于您要过滤的内容:

组件:

  <div *ngFor="let reportList of filteredReports(job)">

ts:

 filteredReports(job: Job)
{
    return job.reportList.filter(r => r.jobUuid == job.Uuid);
}

不确定这是否正是您要过滤的内容,但它提供了思路。

filterByVariable(job: Job) {
    return job.reportList.filter(r=> r.jobUuid == job.jobUuid)
  }


            <mat-card-content *ngIf="!collapsed2">
                <div *ngFor="let reportList of filterByVariable(job)">
                  <p class="title"><b>Transfer Status:</b> {{reportList.transferStatus}}</p>
                  <p class="title"><b>File Size:</b> {{reportList.fileSize}}</p>
                  <p class="title"><b>Last Updated:</b> {{reportList.lastUpdate | date :'medium'}}</p>
                  <p class="title"><b>ADLS Full Path:</b> {{reportList.adlsPath}}</p>
                  <!--                  <br>-->
                  <button class="button-download" class="btn btn-light btn-lg" (click)="downloadFile(reportList.adlsPath)">Download File
                  </button>
                  <br><br>
                </div>
            </mat-card-content>