Reputation: 11
I am relatively new to angular and am having a bit of trouble in my typescript of updating a mat table datasource (declared as datasource :any) inside a subscription.
My function below goes away to the adminservice and makes an api call, the function then loops over the returned array and makes another api call via the adminservice to get some more information about the fleet.
At the bottom part of my code is the original method to update the datasource, but without the extra required data. This works fine, and is quite confusing to me.
Any help would be greatly appreciated.
refresh(): void {
const data = {};
const that = this;
this.adminService.fleets(data).subscribe(result => {
that.fleetTableData = [];
result.forEach(function (fleetObject){
if (typeof fleetObject.fleetTotals === 'undefined'){
fleetObject.fleetTotals = {};
fleetObject.fleetTotals.totalVehicles = 0;
fleetObject.fleetTotals.totalActiveVehicles = 0;
fleetObject.fleetTotals.totalStatusTestedVehicles = 0;
}
that.fleetTableData[fleetObject.fleetId] = fleetObject;
that.adminService.vehicles(
{fleetId: fleetObject.fleetId}
).subscribe(result2 => {
result2.forEach(function (vehicleForFleet) {
var fleetId = vehicleForFleet.fleetId;
that.fleetTableData[fleetId].fleetTotals.totalVehicles = (that.fleetTableData[fleetId].fleetTotals.totalVehicles + 1);
if (typeof vehicleForFleet.commissioning !== 'undefined') {
if (vehicleForFleet.commissioning.commissionStatus === 'tested') {
that.fleetTableData[fleetId].fleetTotals.totalStatusTestedVehicles = (that.fleetTableData[fleetId].fleetTotals.totalStatusTestedVehicles + 1);
}
if (vehicleForFleet.commissioning.commissionStatus === 'active') {
that.fleetTableData[fleetId].fleetTotals.totalActiveVehicles = (that.fleetTableData[fleetId].fleetTotals.totalActiveVehicles + 1);
}
}
});
});
});
// in subscribe doesn't save to that.datasorce
that.dataSource.data = new MatTableDataSource(that.fleetTableData);
that.dataSource.sort = that.sort;
console.log(that.fleetTableData);
});
//out subscribe doest work as it is returning undefined
// console.log(this.fleetTableData);
// this.dataSource = new MatTableDataSource(this.fleetTableData);
// this.dataSource.sort = this.sort;
//works
// const data = {};
// this.adminService.fleets(data).subscribe(result => {
// this.fleets = result;
// this.dataSource = new MatTableDataSource(this.fleets);
// this.dataSource.sort = this.sort;
//
// console.log(result);
// });
}
Upvotes: 0
Views: 4863
Reputation: 44
I had the same problem at one time when I worked with mat-table, I solved this in this way.
this.dataSource = new MatTableDataSource(data)
Upvotes: 0
Reputation: 306
Looking at your code it looks like this.datasource is already a MatTableDatasource. If that is the case then try just setting the .data property to this.fleets instead of a new MatTableDatasource.
this.dataSource.data = that.fleetTableData;
Upvotes: 1
Reputation: 1852
There are two main strategies to address in your code example:
subscribe()
methods, which is an anti-pattern in RxJS. You should only have one subscribe()
, otherwise things will quickly break.subscribe()
should instead be handled by RxJS "operators". This will also help with your nested subscribe()
issue.Here's the strategy I would recommend.
this.adminService.fleets(data).pipe(
map(result=>{
// define and return the data you need for adminService.vehicles
}),
switchMap(fleetId=>this.adminService.vehicles(fleetId)),
map(result2=>{
// Your logic to define and update this.dataSource for your table
})
).subscribe()
The map()
operator will let you take the emitted value and return a new value.
The switchMap()
works the same way as map()
but will let you return a new observable (in this case, your vehicles method that requires the parameter from our first observable.
After that, we use another map()
operator to take the value emitted from adminService.vehicles()
and update the state property this.dataSource
.
Upvotes: 0