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' ;
32import { MatPaginator , MatPaginatorModule } from '@angular/material/paginator' ;
43import { 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' ;
74import { MatTableModule } from '@angular/material/table' ;
85import { MatProgressSpinnerModule } from '@angular/material/progress-spinner' ;
96import { 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