У меня есть мат-таблица, в которой отображается список выполняемых заданий. Я создал две кнопки (Stop и Re-Run) рядом с каждой строкой. Однако я хочу создать мат-спиннер, который будет отображаться только при выполнении задания или когда пользователь нажимает кнопку повторного запуска. Я создал счетчик, но он отображается для всех строк, когда я нажимаю кнопку повторного запуска. Как мне показать это только для строки, на которую я нажал.
Мой HTML-код:
<!-- 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>
<!-- Code for Spinner -->
<ng-container matColumnDef = "spinner">
<mat-header-cell *matHeaderCellDef> </mat-header-cell>
<mat-cell *matCellDef = "let element">
<div *ngIf = "displaySpinner;else doNotShowSpinner">
<mat-spinner></mat-spinner>
</div>
<ng-template #doNotShowSpinner>
</ng-template>
</mat-cell>
</ng-container>
<mat-header-row
*matHeaderRowDef = "jobExecStatDisplayedColumns"
></mat-header-row>
<mat-row
*matRowDef = "
let row;
columns: jobExecStatDisplayedColumns;
let element
"
class = "element-row"
>
</mat-row>
Код машинописного текста:
displaySpinner: boolean = false;
stop_exec_job(element) {
if (element.status == "Running" || element.status == "Pending") {
//Api to stop Job Execution
this.recommendationService
.stopJobExecution(element.jobId, "Cancelled")
.subscribe(data => {
this.executeJobStop = data;
//this.changeStatus.push(this.executeJobStop);
// this.newStatus = new ExampleDataSource();
});
this.displaySpinner = false;
element.status = "Completed";
this.snakbar.statusBar("Job Execution Stopped", "Sucess");
} else {
this.snakbar.statusBar("Job Failed to start", "Failure");
}
}
re_run_job(element) {
if (
element.status == "Cancelled" ||
element.status == "Completed" ||
element.status == "Executed" ||
element.status == "FINISHED"
) {
//Api to Re-Run Job Execution
this.recommendationService
.stopJobExecution(element.jobId, "Running")
.subscribe(data => {
this.executeJobStop = data;
//this.changeStatus.push(this.executeJobStop);
// this.newStatus = new ExampleDataSource();
});
this.displaySpinner = true;
element.status = "Running";
this.snakbar.statusBar("Job Execution Started", "Sucess");
} else {
this.snakbar.statusBar("Job Failed to start", "Failure");
}
}
Кнопка остановки и повторного запуска работает нормально. Если я нажму «Стоп» в строке 2, изменится только статус строки 2. Но если я нажму на запуск строки 1, то счетчик начнет отображаться для всех строк и аналогично для остановки.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Ваше свойство displaySpinner (глобальное свойство) класса используется во всех строках. Вот почему, когда вы нажимаете Re-Run, displaySpinner переключается на true, и, поскольку все строки имеют условие для одного и того же свойства, все они показывают счетчик.
Вместо использования displaySpinner попробуйте использовать element.status.
Измените строки ниже:
<div *ngIf = "displaySpinner;else doNotShowSpinner">
<mat-spinner></mat-spinner>
</div>
ниже:
<div *ngIf = "element.status === 'Running';else doNotShowSpinner">
<mat-spinner></mat-spinner>
</div>
Свяжите счетчик со статусом элемента:
<!-- Code for Spinner -->
<ng-container matColumnDef = "spinner">
<mat-header-cell *matHeaderCellDef> </mat-header-cell>
<mat-cell *matCellDef = "let element">
<div *ngIf = "element.status === 'Running'">
<mat-spinner></mat-spinner>
</div>
<ng-template #doNotShowSpinner>
</ng-template>
</mat-cell>
</ng-container>
Я бы также рекомендовал создать перечисление для ваших статусов для удобочитаемости и согласованности.
Причина, по которой функция stop_exec_job изменяет только статус выбранных строк, заключается в том, что вы фактически устанавливаете статус строк element, которые вы передаете функции.
Ваша функция re_run_job также устанавливает статус (это нормально), но проблема в том, что вы используете одну переменную displaySpinner в своем компоненте для управления видимостью все счетчиков в каждой строке.
To solve your problem, add an additional property on your
element's which stores the status of the spinner for each row separately (e.g.displaySpinner).
Или, если счетчик основан на статусе элемента, вы можете изменить свой HTML, чтобы он выглядел примерно так (и избавиться от вашей переменной displaySpinner):
<div *ngIf = "element.status === 'Pending' || element.status === 'Running'">
<mat-spinner></mat-spinner>
</div>
вам нужно установить displaySpinner внутри каждого объекта элемента вместо глобальной переменной. Потому что это цикл, и вам нужно проверять логику displaySpinner для каждой строки, а не глобальную единственную переменную.