jijo
jijo

Reputation: 815

Observable with multiple MatTableDataSource

I have an angular 6 application which displays multiple mat-tables in a page. Here is how the json looks like.

"job-detail": 
    {
      "JobId": "480960",
      "jobDocMetadata":
        [
            {
                "seq": "1",
                "docID": "524126",
                "type": "Print",
                "title": "Sample"               
            },
            {
                "seq": "2",
                "docID": "524125",
                "type": "Print",
                "title": "Sample"               
            }           
        ],
        "jobStatusHistory":
        [
            {
                "date": "12-04-2018 12:47:16 CST",
                "code": "200",
                "jobStatus": "Job Undergoing Composition",
                "description": "received a new job"
            },
            {
                "date": "12-04-2018 12:48:14 CST",
                "code": "315",
                "jobStatus": "Job successfully delivered",
                "description": "job finished,"
            }           
        ],
        }

I'm trying to display the data from jobDocMetadata and jobStatusHistory in 2 separate mat-tables in the same page. Here is the service which gets the data from a rest service.

findJobDetail(jobID: number): Observable<JobDetail> {
    return this.httpClient.get<JobDetail>(`${this.JOB_DETAIL_URL}`, customHttpOptions).pipe(
      tap(_ => this.log(`Found Job`)),
      catchError(this.handleError<any>('findJobDetail')),
    );
  }

And this is the component code so far, subscribing to the observable and it's working fine.

     public jobDetailObs: Observable<JobDetail>;
     public jobDetail: JobDetail;
     jobDocMetadataDS: MatTableDataSource<JobDocMetadata>;
     jobStatusHistoryDS: MatTableDataSource<JobStatusHistory>;
     @ViewChildren(MatSort)
     sort = new QueryList<MatSort>();

      this.apiService.findJobDetail(this.id).subscribe(
      data => {
        this.jobDetail = data as JobDetail;

        this.jobDocMetadataDS = new MatTableDataSource(this.jobDetail.jobDocMetadata);
        this.jobDocMetadataDS.sort = this.sort.toArray()[0];

        this.jobStatusHistoryDS = new MatTableDataSource(this.jobDetail.jobStatusHistory);
        this.jobStatusHistoryDS.sort = this.sort.toArray()[1];
             }
        )

Here is the template sample.

<h2 class="mat-h2 subheader">Job Document Metadata</h2>
    <div class="mat-elevation-z8">
        <mat-table #table [dataSource]="jobDocMetadataDS" matSort>
            <ng-container matColumnDef="seq">
                <mat-header-cell *matHeaderCellDef mat-sort-header> Seq </mat-header-cell>
                <mat-cell *matCellDef="let row"> {{row.seq}}</mat-cell>
            </ng-container>
            <ng-container matColumnDef="docID">
                <mat-header-cell *matHeaderCellDef mat-sort-header> Doc ID </mat-header-cell>
                <mat-cell *matCellDef="let row"> {{row.docID}}</mat-cell>
            </ng-container>

I'm trying to modify this code to use async pipes, since it has been prefered over subscribing to an observable. For this, I'm trying to bind my datasources to the Observable.

this.jobDetailObs = this.apiService.findJobDetail(this.id).pipe(share());

So my question is how can I bind 2 datasources to an Observable of JobDetail. I couldn't bind Observable directly to the data source since the data I need is inside JobDetail. So I'm thinking to convert the Observable of JobDetail to a JobDetail object (jobDetailObs to jobDetail) to achieve this mapping. Is this the best way to do it and if so, how can I achieve it ?

Upvotes: 0

Views: 1333

Answers (1)

Doğancan Arabacı
Doğancan Arabacı

Reputation: 3982

on before mounting the component, you should create two observables from findJobDetail

const findJobDetail$ = this.apiService.findJobDetail(this.id).pipe(share())

this.jobDocMetadataDS$ = findJobDetail$.pipe(map(<map from job detail to doc meta>))
this.jobStatusHistoryDS$ = findJobDetail$.pipe(map(<map from job detail to status history>))

and use in template with async pipe

Upvotes: 1

Related Questions