Skip to content

Commit 0e6daab

Browse files
committed
docs(material/table): switch http example to resource
Reworks the table HTTP example to use resource instead of `HttpClient`. Fixes #33458.
1 parent 343d920 commit 0e6daab

3 files changed

Lines changed: 62 additions & 70 deletions

File tree

src/components-examples/material/table/table-http/table-http-example.css

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@
55

66
.example-table-container {
77
position: relative;
8-
min-height: 200px;
9-
max-height: 400px;
8+
height: 400px;
109
overflow: auto;
1110
}
1211

src/components-examples/material/table/table-http/table-http-example.html

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
<div class="example-container mat-elevation-z8">
2-
@if (isLoadingResults || isRateLimitReached) {
2+
@if (isLoadingResults() || isRateLimitReached()) {
33
<div class="example-loading-shade">
4-
@if (isLoadingResults) {
5-
<mat-spinner></mat-spinner>
4+
@if (isLoadingResults()) {
5+
<mat-spinner/>
66
}
7-
@if (isRateLimitReached) {
7+
@if (isRateLimitReached()) {
88
<div class="example-rate-limit-reached">
99
GitHub's API rate limit has been reached. It will be reset in one minute.
1010
</div>
@@ -13,9 +13,15 @@
1313
}
1414

1515
<div class="example-table-container">
16-
17-
<table mat-table [dataSource]="data" class="example-table"
18-
matSort matSortActive="created" matSortDisableClear matSortDirection="desc">
16+
<table
17+
mat-table
18+
[dataSource]="data()"
19+
class="example-table"
20+
matSort
21+
(matSortChange)="handleSort()"
22+
matSortActive="created"
23+
matSortDisableClear
24+
matSortDirection="desc">
1925
<!-- Number Column -->
2026
<ng-container matColumnDef="number">
2127
<th mat-header-cell *matHeaderCellDef>#</th>
@@ -47,5 +53,9 @@
4753
</table>
4854
</div>
4955

50-
<mat-paginator [length]="resultsLength" [pageSize]="30" aria-label="Select page of GitHub search results"></mat-paginator>
56+
<mat-paginator
57+
[length]="resultsLength()"
58+
[pageSize]="30"
59+
(page)="handlePage()"
60+
aria-label="Select page of GitHub search results"></mat-paginator>
5161
</div>
Lines changed: 43 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
1-
import {HttpClient} from '@angular/common/http';
2-
import {Component, ViewChild, AfterViewInit, inject} from '@angular/core';
1+
import {Component, viewChild, signal, computed, resource} from '@angular/core';
32
import {MatPaginator, MatPaginatorModule} from '@angular/material/paginator';
43
import {MatSort, MatSortModule, SortDirection} from '@angular/material/sort';
5-
import {merge, Observable, of as observableOf} from 'rxjs';
6-
import {catchError, map, startWith, switchMap} from 'rxjs/operators';
74
import {MatTableModule} from '@angular/material/table';
85
import {MatProgressSpinnerModule} from '@angular/material/progress-spinner';
96
import {DatePipe} from '@angular/common';
@@ -17,54 +14,54 @@ import {DatePipe} from '@angular/common';
1714
templateUrl: 'table-http-example.html',
1815
imports: [MatProgressSpinnerModule, MatTableModule, MatSortModule, MatPaginatorModule, DatePipe],
1916
})
20-
export class TableHttpExample implements AfterViewInit {
21-
private _httpClient = inject(HttpClient);
17+
export class TableHttpExample {
18+
readonly displayedColumns: string[] = ['created', 'state', 'number', 'title'];
19+
readonly paginator = viewChild.required(MatPaginator);
20+
readonly sort = viewChild.required(MatSort);
21+
readonly sortActive = signal('created');
22+
readonly sortDirection = signal<SortDirection>('desc');
23+
readonly pageIndex = signal(0);
2224

23-
displayedColumns: string[] = ['created', 'state', 'number', 'title'];
24-
exampleDatabase: ExampleHttpDatabase | null = null;
25-
data: GithubIssue[] = [];
25+
readonly issueResource = resource({
26+
params: () => ({
27+
sort: this.sortActive(),
28+
order: this.sortDirection(),
29+
page: this.pageIndex(),
30+
}),
31+
loader: async ({params: {sort, order, page}, abortSignal}) => {
32+
const base = 'https://api.github.com/search/issues';
33+
const requestUrl = `${base}?q=repo:angular/components&sort=${sort}&order=${order}&page=${
34+
page + 1
35+
}`;
36+
const response = await fetch(requestUrl, {signal: abortSignal});
37+
if (!response.ok) {
38+
throw new Error('Rate limit reached');
39+
}
40+
return (await response.json()) as GithubApi;
41+
},
42+
});
2643

27-
resultsLength = 0;
28-
isLoadingResults = true;
29-
isRateLimitReached = false;
44+
readonly isLoadingResults = this.issueResource.isLoading;
45+
readonly isRateLimitReached = computed(() => this.issueResource.error() != null);
3046

31-
@ViewChild(MatPaginator) paginator!: MatPaginator;
32-
@ViewChild(MatSort) sort!: MatSort;
47+
readonly data = computed(() => {
48+
if (this.isRateLimitReached()) {
49+
return [];
50+
}
51+
return this.issueResource.value()?.items || [];
52+
});
3353

34-
ngAfterViewInit() {
35-
this.exampleDatabase = new ExampleHttpDatabase(this._httpClient);
54+
readonly resultsLength = computed(() => this.issueResource.value()?.total_count || 0);
3655

37-
// If the user changes the sort order, reset back to the first page.
38-
this.sort.sortChange.subscribe(() => (this.paginator.pageIndex = 0));
39-
40-
merge(this.sort.sortChange, this.paginator.page)
41-
.pipe(
42-
startWith({}),
43-
switchMap(() => {
44-
this.isLoadingResults = true;
45-
return this.exampleDatabase!.getRepoIssues(
46-
this.sort.active,
47-
this.sort.direction,
48-
this.paginator.pageIndex,
49-
).pipe(catchError(() => observableOf(null)));
50-
}),
51-
map(data => {
52-
// Flip flag to show that loading has finished.
53-
this.isLoadingResults = false;
54-
this.isRateLimitReached = data === null;
55-
56-
if (data === null) {
57-
return [];
58-
}
56+
handleSort() {
57+
this.paginator().pageIndex = 0;
58+
this.pageIndex.set(0);
59+
this.sortActive.set(this.sort().active);
60+
this.sortDirection.set(this.sort().direction);
61+
}
5962

60-
// Only refresh the result length if there is new data. In case of rate
61-
// limit errors, we do not want to reset the paginator to zero, as that
62-
// would prevent users from re-triggering requests.
63-
this.resultsLength = data.total_count;
64-
return data.items;
65-
}),
66-
)
67-
.subscribe(data => (this.data = data));
63+
handlePage() {
64+
this.pageIndex.set(this.paginator().pageIndex);
6865
}
6966
}
7067

@@ -79,17 +76,3 @@ export interface GithubIssue {
7976
state: string;
8077
title: string;
8178
}
82-
83-
/** An example database that the data source uses to retrieve data for the table. */
84-
export class ExampleHttpDatabase {
85-
constructor(private _httpClient: HttpClient) {}
86-
87-
getRepoIssues(sort: string, order: SortDirection, page: number): Observable<GithubApi> {
88-
const href = 'https://api.github.com/search/issues';
89-
const requestUrl = `${href}?q=repo:angular/components&sort=${sort}&order=${order}&page=${
90-
page + 1
91-
}`;
92-
93-
return this._httpClient.get<GithubApi>(requestUrl);
94-
}
95-
}

0 commit comments

Comments
 (0)