У меня есть таблица соответствия с развернутой и свернутой строкой, где я отображал список запущенных заданий.
Первоначально я использовал данные-заглушки и смог успешно развернуть и свернуть строки. Теперь я получаю данные из API, и код ломается. Я точно знаю, где он ломается, но я не знаю, как его решить.
HTML код: -
<div class="main-content">
<div class="card">
<div class="card-header">
<h5 class="title">Job Execution Stats</h5>
</div>
<mat-table [dataSource]="jobExecutionStat">
<!-- Id Column -->
<ng-container matColumnDef="jobId">
<mat-header-cell *matHeaderCellDef> ID </mat-header-cell>
<mat-cell *matCellDef="let element">{{ element.jobId }} </mat-cell>
</ng-container>
<ng-container matColumnDef="executionDate">
<mat-header-cell *matHeaderCellDef>
Execution Date
</mat-header-cell>
<mat-cell *matCellDef="let element"
>{{ element.executionDate }}
</mat-cell>
</ng-container>
<!-- Weight Column -->
<ng-container matColumnDef="afterTimePeriod">
<mat-header-cell *matHeaderCellDef>
Current Time Period
</mat-header-cell>
<mat-cell *matCellDef="let element"
>{{ element.afterTimePeriod }}
</mat-cell>
</ng-container>
<!-- Symbol Column -->
<ng-container matColumnDef="previousTimePeriod">
<mat-header-cell *matHeaderCellDef>
Previous Time Period
</mat-header-cell>
<mat-cell *matCellDef="let element"
>{{ element.previousTimePeriod }}
</mat-cell>
</ng-container>
<ng-container matColumnDef="status">
<mat-header-cell *matHeaderCellDef> Status </mat-header-cell>
<mat-cell *matCellDef="let element"
>{{ element.status }}
</mat-cell>
</ng-container>
<!-- Expanded Content Column - The detail row is made up of this one column -->
<ng-container matColumnDef="expandedDetail">
<mat-cell *matCellDef="let detail">
<ng-container *ngIf="displayProgBar">
<mat-toolbar>
<mat-label>JobId: {{ jobId }}</mat-label>
<mat-progress-bar
mode="indeterminate"
class="mat-progress-bar"
color="primary"
>
</mat-progress-bar>
<button
mat-icon-button
(click)="stop_exec_job2()"
matTooltip="Stop Executing the Job"
>
<!-- Edit icon for row -->
<i class="material-icons" style="color:red">
stop
</i>
</button>
</mat-toolbar>
</ng-container>
<ng-container *ngIf ="!displayProgBar">
Job Execution is Completed
</ng-container>
</mat-cell>
</ng-container>
<!-- Code for Stop and Re-Run Buttons -->
<ng-container matColumnDef="actions">
<mat-header-cell *matHeaderCellDef> </mat-header-cell>
<mat-cell *matCellDef="let element; let index = index">
<button
mat-icon-button
(click)="stop_exec_job(element)"
matTooltip="Stop Executing the Job"
[disabled]="element.status == 'Completed'"
>
<!-- Edit icon for row -->
<i class="material-icons" style="color:red"> stop </i>
</button>
<!-- Delete icon for row -->
<button
mat-icon-button
(click)="re_run_job(element)"
matTooltip="Re-Run the Job"
[disabled]="
element.status == 'Running' ||
element.status == 'Pending'
"
>
<i class="material-icons" style="color:green">
cached
</i>
</button>
</mat-cell>
</ng-container>
<mat-header-row
*matHeaderRowDef="jobExecStatDisplayedColumns"
></mat-header-row>
<mat-row
*matRowDef="
let row;
columns: jobExecStatDisplayedColumns;
let element
"
matRipple
class="element-row"
[class.expanded]="expandedElement == row"
(click)="expandedElement === row? expandedElement = null : expandedElement = row"
(click)="showProgressBar(element)"
>
</mat-row>
<mat-row
*matRowDef="
let row;
columns: ['expandedDetail'];
when: isExpansionDetailRow
"
[@detailExpand]="
row.element == expandedElement ? 'expanded' : 'collapsed'
"
style="overflow: hidden"
>
</mat-row>
</mat-table>
</div>
машинописный код: -
import { Component, OnInit, ɵConsole } from "@angular/core";
import { MatTableDataSource } from "@angular/material";
import { GlobalAppSateService } from "../../services/globalAppSate.service";
import { DataService } from "../../services/data.service";
import { SnakBarComponent } from "../custom-components/snak-bar/snak-
bar.component";
import { DataSource } from "@angular/cdk/collections";
import { Observable, of } from "rxjs";
import {
animate,
state,
style,
transition,
trigger
} from "@angular/animations";
import { RecommendationService } from '../recommendation-service.service';
@Component({
selector: "app-job-execution-screen",
templateUrl: "./job-execution-screen.component.html",
styleUrls: ["./job-execution-screen.component.scss"],
animations: [
trigger("detailExpand", [
state(
"collapsed",
style({ height: "0px", minHeight: "0", visibility: "hidden" })
),
state("expanded", style({ height: "*", visibility: "visible" })),
transition(
"expanded <=> collapsed",
animate("225ms cubic-bezier(0.4, 0.0, 0.2, 1)")
)
])
]
})
export class JobExecutionScreenComponent implements OnInit {
displayProgBar: boolean = false;
jobId: string;
static jobExecutionList:any;
jobExecStatDisplayedColumns = [
"jobId",
"executionDate",
"previousTimePeriod",
"afterTimePeriod",
"status",
"actions"
];
public selectedElem: any;
projectId:any = 1;
// jobExecutionStat = new MatTableDataSource<Element>(ELEMENT_DATA);
jobExecutionStat = new ExampleDataSource();
isExpansionDetailRow = (i: number, row: Object) =>
row.hasOwnProperty("detailRow");
expandedElement: any;
constructor(
private dataService: DataService,
public globalAppSateService: GlobalAppSateService,
private snakbar: SnakBarComponent,
private recommendationService: RecommendationService
) {}
ngOnInit() {
const project = JSON.parse(this.dataService.getObject("project"));
if (project != null) {
this.globalAppSateService.onMessage(project);
}
this.recommendationService.getJobExecutionStatList(this.projectId).
subscribe( data => {
JobExecutionScreenComponent.jobExecutionList = data;
});
}
stop_exec_job(element) {
if (element.status == "Running" || element.status == "Pending") {
this.displayProgBar = false;
this.snakbar.statusBar("Job Execution Stopped", "Sucess");
element.status = "Completed";
}
}
stop_exec_job2() {
this.stop_exec_job(this.selectedElem);
this.displayProgBar = false;
}
re_run_job(element) {
if (element.status == "Completed") {
this.snakbar.statusBar("Job Execution Started", "Sucess");
element.status = "Running";
}
}
showProgressBar(element) {
this.selectedElem = element;
this.jobId = element.id;
console.log(this.jobId);
if (element.status == "Running" || element.status == "Pending") {
this.displayProgBar = true;
}
}
}
// const ELEMENT_DATA: Element[] = [
// {
// id: 1,
// exec_date: "17-01-2016",
// prev_time_period: "2016-04,2016-05,2016-06",
// curr_time_period: "2016-08",
// status: "Completed"
// },
// {
// id: 2,
// exec_date: "17-01-2017",
// prev_time_period: "2017-04,2017-05,2017-06",
// curr_time_period: "2017-08",
// status: "Running"
// },
// {
// id: 3,
// exec_date: "27-07-2017",
// prev_time_period: "2017-45,2017-46,2017-47",
// curr_time_period: "2018-01,2018-02",
// status: "Pending"
// },
// {
// id: 4,
// exec_date: "17-10-2018",
// prev_time_period: "2017-30,2017-31,2017-32",
// curr_time_period: "2018-01,2018-02",
// status: "Completed"
// },
// {
// id: 5,
// exec_date: "21-01-2018",
// prev_time_period: "2016-01,2016-02,2016-03,2016-04",
// curr_time_period: "2016-52",
// status: "Pending"
// },
// {
// id: 6,
// exec_date: "17-01-2018",
// prev_time_period: "2017-31,2017-32,2017-33,2017-34",
// curr_time_period: "2017-52",
// status: "Running"
// }
// ];
export interface Element {
projectId: number;
id: number;
exec_date: Date;
prev_time_period: string;
curr_time_period: string;
status: string;
}
export class ExampleDataSource extends DataSource<any> {
/** Connect function called by the table to retrieve one stream containing
the data to render. */
connect(): Observable<Element[]> {
const rows = [];
JobExecutionScreenComponent.jobExecutionList.forEach(element =>
rows.push(element, { detailRow: true, element })
);
console.log(rows);
return of(rows);
}
disconnect() {}
}
Изначально в Typescript в компоненте ExampleDataSource я использовал ELEMENT_DATA.forEach (element =>
rows.push (element, {detailRow: true, element})
Теперь я использую переменную, в которой я храню данные API, и это дает мне ошибку.
Я сделал JobExecutionList статическим, чтобы я мог использовать его вне моего класса, т.е. в классе ExampleDataSource.