@@ -34,6 +34,11 @@ export class GridOdataComponent implements OnInit {
3434 </ul>
3535 <li>OData Service could be replaced by other Service type in the future (GraphQL or whichever you provide)</li>
3636 <li>You can also preload a grid with certain "presets" like Filters / Sorters / Pagination <a href="https://github.com/ghiscoding/Angular-Slickgrid/wiki/Grid-State-&-Preset" target="_blank">Wiki - Grid Preset</a>
37+ <li><span class="text-danger">NOTE:</span> For demo purposes, the last column (filter & sort) will always throw an
38+ error and its only purpose is to demo what would happen when you encounter a backend server error
39+ (the UI should rollback to previous state before you did the action).
40+ Also changing Page Size to 50,000 will also throw which again is for demo purposes.
41+ </li>
3742 </ul>
3843 ` ;
3944 angularGrid ! : AngularGridInstance ;
@@ -47,6 +52,8 @@ export class GridOdataComponent implements OnInit {
4752 odataVersion = 2 ;
4853 odataQuery = '' ;
4954 processing = true ;
55+ errorStatus = '' ;
56+ isPageErrorTest = false ;
5057 status = { text : 'processing...' , class : 'alert alert-danger' } ;
5158
5259 constructor ( private readonly cd : ChangeDetectorRef , private http : HttpClient ) { }
@@ -72,7 +79,7 @@ export class GridOdataComponent implements OnInit {
7279 collection : [ { value : '' , label : '' } , { value : 'male' , label : 'male' } , { value : 'female' , label : 'female' } ]
7380 }
7481 } ,
75- { id : 'company' , name : 'Company' , field : 'company' } ,
82+ { id : 'company' , name : 'Company' , field : 'company' , filterable : true , sortable : true } ,
7683 ] ;
7784
7885 this . gridOptions = {
@@ -92,7 +99,7 @@ export class GridOdataComponent implements OnInit {
9299 enableRowSelection : true ,
93100 enablePagination : true , // you could optionally disable the Pagination
94101 pagination : {
95- pageSizes : [ 10 , 15 , 20 , 25 , 30 , 40 , 50 , 75 , 100 ] ,
102+ pageSizes : [ 10 , 20 , 50 , 100 , 500 , 50000 ] ,
96103 pageSize : defaultPageSize ,
97104 totalItems : 0
98105 } ,
@@ -113,7 +120,14 @@ export class GridOdataComponent implements OnInit {
113120 enableCount : this . isCountEnabled , // add the count in the OData query, which will return a property named "odata.count" (v2) or "@odata.count" (v4)
114121 version : this . odataVersion // defaults to 2, the query string is slightly different between OData 2 and 4
115122 } ,
116- preProcess : ( ) => this . displaySpinner ( true ) ,
123+ onError : ( error : Error ) => {
124+ this . errorStatus = error . message ;
125+ this . displaySpinner ( false , true ) ;
126+ } ,
127+ preProcess : ( ) => {
128+ this . errorStatus = '' ;
129+ this . displaySpinner ( true ) ;
130+ } ,
117131 process : ( query ) => this . getCustomerApiCall ( query ) ,
118132 postProcess : ( response ) => {
119133 this . metrics = response . metrics ;
@@ -125,11 +139,15 @@ export class GridOdataComponent implements OnInit {
125139 } ;
126140 }
127141
128- displaySpinner ( isProcessing : boolean ) {
142+ displaySpinner ( isProcessing : boolean , isError ?: boolean ) {
129143 this . processing = isProcessing ;
130- this . status = ( isProcessing )
131- ? { text : 'processing...' , class : 'alert alert-danger' }
132- : { text : 'done' , class : 'alert alert-success' } ;
144+ if ( isError ) {
145+ this . status = { text : 'ERROR!!!' , class : 'alert alert-danger' } ;
146+ } else {
147+ this . status = ( isProcessing )
148+ ? { text : 'loading...' , class : 'alert alert-warning' }
149+ : { text : 'finished' , class : 'alert alert-success' } ;
150+ }
133151 }
134152
135153 getCustomerCallback ( data : any ) {
@@ -180,7 +198,7 @@ export class GridOdataComponent implements OnInit {
180198 /** This function is only here to mock a WebAPI call (since we are using a JSON file for the demo)
181199 * in your case the getCustomer() should be a WebAPI function returning a Promise
182200 */
183- getCustomerDataApiMock ( query : string ) {
201+ getCustomerDataApiMock ( query : string ) : Promise < any > {
184202 // the mock is returning a Promise, just like a WebAPI typically does
185203 return new Promise ( ( resolve , reject ) => {
186204 const queryParams = query . toLowerCase ( ) . split ( '&' ) ;
@@ -190,9 +208,17 @@ export class GridOdataComponent implements OnInit {
190208 let countTotalItems = 100 ;
191209 const columnFilters = { } ;
192210
211+ if ( this . isPageErrorTest ) {
212+ this . isPageErrorTest = false ;
213+ throw new Error ( 'Server timed out trying to retrieve data for the last page' ) ;
214+ }
215+
193216 for ( const param of queryParams ) {
194217 if ( param . includes ( '$top=' ) ) {
195218 top = + ( param . substring ( '$top=' . length ) ) ;
219+ if ( top === 50000 ) {
220+ throw new Error ( 'Server timed out retrieving 50,000 rows' ) ;
221+ }
196222 }
197223 if ( param . includes ( '$skip=' ) ) {
198224 skip = + ( param . substring ( '$skip=' . length ) ) ;
@@ -229,9 +255,19 @@ export class GridOdataComponent implements OnInit {
229255 const fieldName = filterMatch ! [ 1 ] . trim ( ) ;
230256 ( columnFilters as any ) [ fieldName ] = { type : 'ends' , term : filterMatch ! [ 2 ] . trim ( ) } ;
231257 }
258+
259+ // simular a backend error when trying to sort on the "Company" field
260+ if ( filterBy . includes ( 'company' ) ) {
261+ throw new Error ( 'Server could not filter using the field "Company"' ) ;
262+ }
232263 }
233264 }
234265
266+ // simular a backend error when trying to sort on the "Company" field
267+ if ( orderBy . includes ( 'company' ) ) {
268+ throw new Error ( 'Server could not sort using the field "Company"' ) ;
269+ }
270+
235271 const sort = orderBy . includes ( 'asc' )
236272 ? 'ASC'
237273 : orderBy . includes ( 'desc' )
@@ -303,6 +339,31 @@ export class GridOdataComponent implements OnInit {
303339 console . log ( 'Client sample, Grid State changed:: ' , gridStateChanges . change ) ;
304340 }
305341
342+ throwPageChangeError ( ) {
343+ this . isPageErrorTest = true ;
344+ this . angularGrid ?. paginationService ?. goToLastPage ( ) ;
345+ }
346+
347+ // YOU CAN CHOOSE TO PREVENT EVENT FROM BUBBLING IN THE FOLLOWING 3x EVENTS
348+ // note however that internally the cancelling the search is more of a rollback
349+ handleOnBeforeSort ( e : Event ) {
350+ // e.preventDefault();
351+ // return false;
352+ return true ;
353+ }
354+
355+ handleOnBeforeSearchChange ( e : Event ) {
356+ // e.preventDefault();
357+ // return false;
358+ return true ;
359+ }
360+
361+ handleOnBeforePaginationChange ( e : Event ) {
362+ // e.preventDefault();
363+ // return false;
364+ return true ;
365+ }
366+
306367 // THE FOLLOWING METHODS ARE ONLY FOR DEMO PURPOSES DO NOT USE THIS CODE
307368 // ---
308369
0 commit comments