Atlas91
Atlas91

Reputation: 5904

Fill table in Async way

I have a table with a lot of data. I would get these data from server row by row with async requests. On every response I would fill the table with a new row. In this way the user should be able to see the table filling step by step and not in one time. The request is by name and by date. So, that's an example I've done so far:

dataObj$: Observable<{}>;

this.allDates.forEach(date => {
            let timeStamp = moment(date).valueOf();
            this.dataObj$ = this.service.getData(userName, timeStamp);
        });

this is the result:

{"date":1593900000000,"done":12,"progress":30}

And this is the table

<table>
  <tr>
    <th>

    </th>
    <th scope="col">
      Done
    </th>
    <th>
      Progress
    </th>
  </tr>
  <tr>
    <th scope="row">{{(dataObj$ | async)?.date | date: 'dd/MM/yyyy'}}</th>
    <td>{{(dataObj$ | async)?.done}}</td>
    <td>{{(dataObj$ | async)?.progress}}</td>
  </tr>
</table>

In this way I have a table with all dates in the first column, Done and Progress labels as headers and the other data to fill the rest of the table. Something like

      Done  Progress
data1  1       1    
data2  2       2    
data3  3       3

but it's not working like this actually. Right now the table is showing me just only the last row. What I want is different. It should show me that it creates row by row as soon as the request is finished. What's wrong here?

Upvotes: 0

Views: 1418

Answers (1)

Poul Kruijt
Poul Kruijt

Reputation: 71921

You can use the concat operator with the scan operator to combine all results:

interface DataObject {
  date: number;
  progress: number;
  dont: number;
}

readonly data$: Observable<DataObject[]> = concat(
  ...this.allDates.map((date) => this.service.getData(userName, moment(date).valueOf()))
).pipe(
  scan((dates, date) => {
    dates.push(date);

    return dates;
  }, [])
)

trackByDate(i: number, data: DataObject): number {
  return data.date;
}

Which you can use in your table:

<table>
  <tr>
    <th></th>
    <th scope="col">Done</th>
    <th>Progress</th>
  </tr>
  <tr *ngFor="let data of data$ | async; trackBy: trackByDate">
    <td>{{ data.date | date: 'dd/MM/yyyy' }}</td>
    <td>{{ data.done }}</td>
    <td>{{ data.progress }}</td>
  </tr>
</table>

Working example with mock request

Upvotes: 1

Related Questions