Reputation: 185
I am new to RxResource API with angular 19. The issue is that the material table doesn't display data loading from rxResource (but there is a little trick that I can make to display it. It doesn't make sense at all the way I did). Here is my code: my template:
<mat-table #table [dataSource]="dataSource" matSort class="mat-elevation-z8" multiTemplateDataRows>
<ng-container matColumnDef="webTubeLink">
<mat-header-cell *matHeaderCellDef mat-sort-header>Tube Link</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.webTubeLink}}</mat-cell>
</ng-container>
<ng-container matColumnDef="videoId">
<mat-header-cell *matHeaderCellDef mat-sort-header>Video Id</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.videoId}}</mat-cell>
</ng-container>
<ng-container matColumnDef="title">
<mat-header-cell *matHeaderCellDef mat-sort-header>Title</mat-header-cell>
<mat-cell *matCellDef="let row">{{row.webTubeTitle}}</mat-cell>
</ng-container>
<ng-container matColumnDef="actions">
<mat-header-cell *matHeaderCellDef>
<span><i class='bi bi-plus-circle' (click)="addNew()"></i> Add</span>
</mat-header-cell>
<mat-cell *matCellDef="let row; let i=index;">
<span class='bi bi-pencil-fill' (click)="startEdit(row)" style="margin-right: 1rem"> Edit</span>
<span class='bi bi-trash-fill' (click)="deleteItem(row)"> Delete</span>
</mat-cell>
</ng-container>
<mat-header-row *matHeaderRowDef="displayedColumns"></mat-header-row>
<mat-row *matRowDef="let row; columns: displayedColumns;"></mat-row>
</mat-table>
<mat-paginator [pageSizeOptions]="[5, 10, 20]" showFirstLastButtons></mat-paginator>
</div>
here is my code component:
tubeRecordsRS = rxResource<any[], any>({
loader: () => this.http.get<any[]>('/Tube/Gettubes')
});
tubeRecords = computed(() => {
this.dataSource = new MatTableDataSource(this.tubeRecordsRS.value());
this.dataSource.paginator = this.paginator;
return this.tubeRecordsRS.value();
})
Here is my fix to display data in material table by adding the code below to the template
<p style="display: none">{{ tubeRecords() | json }}</p>
with the code the app is working as it supposed to.
Why? What did I do wrong? Is there any other way to fix this issue?
Upvotes: 1
Views: 97
Reputation: 17758
As you can read in the docs, the computation inside the computed
function is only executed if the signal value is actually read, which is not the case in your app, unless the paragraph is added which includes the signal read. Which means that your data source is never constructed.
A better way to connect your data source with the resource's data is via an effect
:
export class YourComponent implements AfterViewInit {
tubeRecordsRS = rxResource<any[], any>({
loader: () => this.http.get<any[]>('/Tube/Gettubes')
});
dataSource = new MatTableDataSource();
constructor() {
effect(() => {
this.dataSource.data = this.tubeRecordsRS.value();
});
}
ngAfterViewInit() {
this.dataSource.paginator = this.paginator;
}
}
Upvotes: 1
Reputation: 57986
This can be classified as derived
state, we can achieve it in two ways:
rxResource
loader using rxjs operators:tubeRecordsRS = rxResource<any[], any>({
loader: () => this.http.get<any[]>('/Tube/Gettubes').pipe(
map((response: any) => {
const dataSource = new MatTableDataSource(response);
dataSource.paginator = this.paginator;
return dataSource;
})
)
});
<mat-table #table [dataSource]="tubeRecordsRS.value()" matSort class="mat-elevation-z8" multiTemplateDataRows>
...
computed
to get the data source:tubeRecordsRS = rxResource<any[], any>({
loader: () => this.http.get<any[]>('/Tube/Gettubes')
});
tubeRecords = computed(() => {
const dataSource = new MatTableDataSource(this.tubeRecordsRS.value());
dataSource.paginator = this.paginator;
return dataSource;
})
<mat-table #table [dataSource]="tubeRecords()" matSort class="mat-elevation-z8" multiTemplateDataRows>
...
Upvotes: 1