Reputation: 195
I have built a table from angular materials. I have an object called "matricula" and in the first column I print the property matricula.matricula from a list of matriculas. In the second column I want to print some data I get calling a method from that matricula.matricula. I have my method defined in my Typescrypt document but as it works with a webservice, I only want to call the method for the objects that are shown at each moment (which variates as I have a paginator). I have tried calling the method from the view using {{method}}, but as Angular views work on real time, the method is being called all the time and the project crashes.
How could I do the call only once for each object matricula? I am sure it must be possible but I have no idea which tool or method I should use.
Here is the code from the view:
<ng-container matColumnDef="matricula" style="flex: 0 0 10%;" >
<th mat-header-cell *matHeaderCellDef> Matrícula </th>
<td mat-cell *matCellDef="let matricula"height=70px> {{matricula.matricula}} </td>
</ng-container>
<ng-container matColumnDef="posicion" style="flex: 0 0 50%;">
<th mat-header-cell *matHeaderCellDef> Ubicación </th>
<td mat-cell *matCellDef="let matricula" height=70px> {{method(matricula.matricula)}} </td>
</ng-container>
<tr mat-header-row *matHeaderRowDef="mostrarColumnas"></tr>
<tr mat-row *matRowDef="let matricula; columns: mostrarColumnas;"></tr>
</table>
Edit: Here is the code from the method:
let matricula : MatriculaBuscada = {
action : "ultima_posicion",
matricula : placa
}
this.posicionService.posicion(matricula).subscribe(datos => {
return datos;});
console.log('método getDatos')
}
The posicionService only calls a webservice which sends back a Json that is already mapped.
Upvotes: 1
Views: 1540
Reputation: 57939
If you can not "paginate" your API (see this SO), I imagine that the best bet is subscribe to the matPaginator.changes.
I imagine you has a service with two functions: getAllData -that return the data incomplete- and getData(id) -that return the auxiliar data of one item
You can has in ngAfterViewInit some like: -I used in the e.g. the tipical material table with the periodic elements
ngAfterViewInit() {
//I use the setTimeout for avoid
// the error "ExpressionChangedAfterItHasBeenCheckedError"
setTimeout(()=>{
//simple get the data, getAllData simply return an array os "positions"
this.dataService.getAllData().pipe(
map((res: any[]) => {
//create an object with all the properties necesary
return res.map((x) => ({
position: x, //<--this is the only I get
name: null, //the rest properties I put as null
weight: 0,
symbol: null,
yet: false, //<--add this new property
}));
})
).subscribe((res:any[])=>{
this.dataSource=new MatTableDataSource(res)
this.dataSource.paginator = this.paginator;
this.initPaginator() //<--this is the "key"
});
})
}
initPaginator(){
//I subscribe to paginator.page
//happens always you change the page or the page size
this.paginator.page.pipe(
startWith(1),
).subscribe((_) => {
//get the data that really is showed
//and filter only I not loaded before
const data = this.dataSource.filteredData
.slice(
this.paginator.pageIndex * this.paginator.pageSize,
(this.paginator.pageIndex + 1) * this.paginator.pageSize
)
.filter((x: any) => !x.yet);
//if there're data
if (data.length) {
this.isLoadingResults=true;
//create a forkJoin -and array of Observables-
//e.g. at first is a forkJoin of the array:
//[this.dataService.getData(1),
// this.dataService.getData(2),
// ...]
forkJoin(
data.map((x: any) => this.dataService.getData(x.position))
).subscribe((res: any[]) => {
//in subscribe, try to find the data
res.forEach((x) => {
let item = this.dataSource.data.find(
(d: any) => (d.position == x.position)
);
//and put the properties I received
if (item) {
item.name=x.name;
item.weight=x.weight;
item.symbol=x.symbol;
item.yet=true;
}
});
this.isLoadingResults=false
});
}
});
}
You can see the stackblitz
Upvotes: 1