I have a basic Angular component as follows. From this component, I generate an array of objects of type TestObj and use the same array to make synchronous post-call for all elements of under the condition that if kth (0 <= k <= x.length) element fails to process, the remainder of the array is not processed.
processing-component.component.ts
import { Component, OnInit } from "@angular/core";
import { FormBuilder, Form, FormGroup } from "@angular/forms";
import { Router } from "@angular/router";
import { processingService } from "./processing-component.service";
import { catchError, finalize, map } from "rxjs/operators";
import { concat } from "rxjs/observable/concat";
import { Observable, BehaviorSubject } from "rxjs";
export class TestObj {
processedFor:string;
isProcessingHappened: boolean ;
isProcessingSuccess: boolean;
constructor(isProcessingHappened,isProcessingSuccess) {
this.isProcessingHappened = isProcessingHappened;
this.isProcessingSuccess = isProcessingSuccess;
}
}
@Component({
selector: 'processing-component',
templateUrl: './processing-component.component.html',
styleUrls:['./processing-component.component.scss'],
providers: [ProcessingService]
})
export class ProcessingComponent {
constructor(private processingService: ProcessingService) { }
//some array generation logic to fetch arrayToProcess
public arrayToProcess: Array<TestObj>= [];
public displayedColumns: string[] = ['processedFor', 'isProcessingHappened', 'isProcessingSuccess']
public startBatchRun() {
const processes = this.arrayToProcess.map(details => this.processingService.runBatchExperiment(details).pipe(
map(() => {
this.isLoading.next(true);
details.isProcessingSuccess = true;
return this.arrayToProcess;
}),
catchError(() => {
this.isLoading.next(false);
details.isProcessingSuccess = false;
throw(false);
}),
finalize(() => {
this.isLoading.next(false);
details.isProcessingHappened = true;
}),
));
concat(...processes)
.map(() => this.isLoading = true)
.subscribe(res => {
})
}
}
My service looks as follows
processing-component.service.ts
import { Injectable, Inject } from "@angular/core";
import { Http } from "@angular/http";
@Injectable()
export class ProcessingService {
constructor(@Inject('portfolioBaseUrl') private portfolioBaseUrl: string,
private http: Http) {}
processingUrl = this.portfolioBaseUrl + '/process/'
public runBatchExperiment(processingObj:TestObj ) {
return this.http.post(`${this.processingUrl}`,processingObj);
}
}
My template is as follows
processing-component.component.html
<button *ngIf = "arrayToProcess.length > 0" mat-raised-button (click) = "startBatchRun()" >Start Processing</button>
<div *ngIf = "arrayToProcess.length > 0" >
<mat-table [dataSource] = "arrayToProcess" >
<ng-container matColumnDef="processedFor">
<mat-header-cell *matHeaderCellDef> ID</mat-header-cell>
<mat-cell *matCellDef="let element"> {{element.processedFor }} </mat-cell> <!--add pipe here-->
</ng-container>
<ng-container matColumnDef="isProcessingHappened">
<mat-header-cell *matHeaderCellDef> Proceesing happened </mat-header-cell>
<mat-cell *matCellDef="let element">
<mat-icon *ngIf = "element.isProcessingHappened === true" >done</mat-icon>
<mat-icon *ngIf = "element.isProcessingHappened === false" >error_outline</mat-icon>
</mat-cell>
</ng-container>
<ng-container matColumnDef="isProcessingSuccess">
<mat-header-cell *matHeaderCellDef> Batch success </mat-header-cell>
<mat-cell *matCellDef="let element">
<mat-icon *ngIf = "element.isProcessingSuccess === true" >done</mat-icon>
<mat-icon *ngIf = "element.isProcessingSuccess === false" >error_outline</mat-icon>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
</div>
What additionally I want to do is display a progress spinner which gets displayed when the post-call goes for an object of type TestObj and gets hidden when we get a response from the back-end for the particular object. This progress spinner must disable the UI screen completely.
I tried using an interceptor service to achieve the same. The problem with that is the interceptor displays the progress spinner for all the calls made by the entire front end and what I am trying to achieve is to do the same, but only for the http calls made by ProcessingComponent alone. I tried to take a local variable isLoading
and set it to false in the constructor
of ProcessingComponent
and on the execution of startBatchRun
, I set isLoading
to true and set the same to false on the exit of startBatchRun
. Is there any way that I can achieve the functionality from the observable pipe?