TypeError: Невозможно прочитать свойство 'forEach' из неопределенного при чтении данных из API вместо данных-заглушек - PullRequest
0 голосов
/ 23 января 2019

У меня есть таблица соответствия с развернутой и свернутой строкой, где я отображал список запущенных заданий. Первоначально я использовал данные-заглушки и смог успешно развернуть и свернуть строки. Теперь я получаю данные из 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> &nbsp;
                        <mat-progress-bar
                            mode="indeterminate"
                            class="mat-progress-bar"
                            color="primary"
                        >
                        </mat-progress-bar>
                        &nbsp;&nbsp;
                        <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.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...