【问题标题】:passing data from mat-table to mat-card in same component在同一组件中将数据从 mat-table 传递到 mat-card
【发布时间】:2020-03-02 19:06:55
【问题描述】:

我有一个带有 mat-table 的组件,我可以在 html 文件中使用我的数据源中的变量。我的桌子有一个扩展面板,可以打开一张垫卡。我还需要从用于数据源的同一类中传递参数。虽然我可以轻松访问参数,但我希望它们按特定字段过滤,但我不知道该怎么做。我知道 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)

  }

}

类文件

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吗?
  • 是的,报告列表。实际上,它是reportList和batchList,但是一旦我知道如何做一个,我确定我可以做另一个

标签: angular parameter-passing mat-table


【解决方案1】:

如果我做对了(我可能做错了),您希望将显示的 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);
}

不确定这是否正是您要过滤的内容,但它给出了想法。

【讨论】:

  • 这段代码的问题在于,如果我删除了内部循环(
    ,我把这个:
    的报告列表,我收到一个错误,报告列表未定义。作业对象是来自我的 api 的 jsonObject,实际上不在组件中(如您的 Stackblitz 示例)
  • 好的,只要你有 this.jobs = res;在您的组件中,因此看起来 this.jobs 包含来自 ngOnInit 中调用的 api 的数据。此外,您可能需要根据需要更改过滤功能,这只是过滤方式的一个示例。例如。如果 this.jobs 有数据并且在你的函数中你确实返回 this.jobs[0].reportList;那么这应该是测试过滤器是否可以正常工作。回答如何将参数传递给组件进行过滤的问题。
  • 另见编辑后的答案以了解其他功能示例。
  • 感谢 JMP 的帮助。我仍然无法使它工作。我想知道是不是因为我的jobUuid是一个字符串而不是一个数字,因此不能用作索引(让reportListof job.reportListof let jobUuid = index”)
  • 澄清一下,我需要通过Uuid过滤reportList,这与Job类中的jobUuid相同
【解决方案2】:
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>

【讨论】:

    猜你喜欢
    相关资源
    最近更新 更多
    热门标签