From 70acb9b18bdabe8e8efc746281f866ffe8581dd2 Mon Sep 17 00:00:00 2001 From: ttonev Date: Thu, 12 Sep 2024 14:54:28 +0300 Subject: [PATCH 1/2] docs(grids): added remote samples for grid and hgrid --- .../grids/_shared/remote-data-operations.md | 471 +++++++++++++++++- docfx/en/components/toc.json | 2 +- 2 files changed, 464 insertions(+), 9 deletions(-) diff --git a/doc/en/components/grids/_shared/remote-data-operations.md b/doc/en/components/grids/_shared/remote-data-operations.md index 137b92ee4..e62a8e1a8 100644 --- a/doc/en/components/grids/_shared/remote-data-operations.md +++ b/doc/en/components/grids/_shared/remote-data-operations.md @@ -251,9 +251,6 @@ public handlePreLoad() { `sample="/{ComponentSample}/infinite-scroll", height="550", alt="{Platform} {ComponentTitle} Remote Data Operations Infinite Scroll Example"` - - - ## Remote Sorting/Filtering @@ -492,12 +489,16 @@ BLAZOR CODE SNIPPET HERE
+ + ## Remote Paging The paging feature can operate with remote data. In order to demonstrate this let's first declare our service that will be responsible for data fetching. We will need the count of all data items in order to calculate the page count. This logic will be added to our service. + + ```typescript @Injectable() export class RemotePagingService { @@ -529,16 +530,120 @@ export class RemotePagingService { } } ``` + + + + +```ts +export class RemotePagingService { + public remoteData: BehaviorSubject = new BehaviorSubject([]); + public dataLength: BehaviorSubject = new BehaviorSubject(0); + public url = 'https://www.igniteui.com/api/products'; + + constructor() {} + + public async getData(index?: number, perPage?: number): Promise { + let qS = ''; + + if (index !== undefined && perPage !== undefined) { + qS = `?$skip=${index}&$top=${perPage}&$count=true`; + } + + try { + const response = await fetch(`${this.url + qS}`); + if (!response.ok) { + throw new Error('Network response was not ok'); + } + const data = await response.json(); + return data; + } catch (error) { + console.error('Error fetching data:', error); + throw error; // Propagate the error further + } +} + +public async getDataLength(): Promise { + try { + const response = await fetch(this.url); + if (!response.ok) { + throw new Error('Network response was not ok'); + } + const data = await response.json(); + return data.length; // Assuming the length is directly accessible in the JSON response + } catch (error) { + console.error('Error fetching data length:', error); + throw error; // Propagate the error further + } +} +``` + + + + +As Blazor Server is already a remote instance, unlike the demos in the other platforms we do not need to set another remote instance for the data, as the data is already remote. In order to do remote paging, we just need to set a couple of methods ins the data class ```razor -BLAZOR CODE SNIPPET HERE + public Task> GetData(int index, int perPage) + { + var itemsToReturn = items.Skip(index).Take(perPage).ToList(); + return Task.FromResult(itemsToReturn); + } + + public Task GetDataLength() + { + return Task.FromResult(items.Count); + } +``` + + + +```tsx +const URL = `https://data-northwind.indigo.design/`; + +export class RemoteService { + +public getData(dataState: any, index?: number, perPage?: number): any { + return fetch(this.buildUrl(dataState, index, perPage)) + .then((result) => result.json()); +} + +private buildUrl(dataState: any, index?: number, perPage?: number) { + let qS = ""; + if (dataState) { + qS += `${dataState.key}`; + } + + // Add index and perPage to the query string if they are defined + if (index !== undefined) { + qS += `?index=${index}`; + if (perPage !== undefined) { + qS += `&perPage=${perPage}`; + } + } else if (perPage !== undefined) { + qS += `?perPage=${perPage}`; + } + + return `${URL}${qS}`; +} + +public getDataLength(dataState: any): Promise { + return fetch(this.buildUrl(dataState)) + .then((result) => result.json()) + .then((data) => data.length); +} +} ``` + + + + The paging feature can operate with remote data. In order to demonstrate this let's first declare our service that will be responsible for data fetching. We will need the count of all data items in order to calculate the page count. This logic will be added to our service. + ```typescript @Injectable() export class RemotePagingService { @@ -571,15 +676,114 @@ export class RemotePagingService { } ``` + + + +```ts +const URL = `https://data-northwind.indigo.design/`; + + + +export function getData(dataState: any, index?: number, perPage?: number): any { + return fetch(buildUrl(dataState, index, perPage)) + .then((result) => result.json()); +} + +function buildUrl(dataState: any, index?: number, perPage?: number) { + let qS = ""; + if (dataState) { + if (dataState.rootLevel) { + qS += `${dataState.key}`; + } else { + qS += `${dataState.parentKey}/${dataState.parentID}/${dataState.key}`; + } + } + + // Add index and perPage to the query string if they are defined + if (index !== undefined) { + qS += `?index=${index}`; + if (perPage !== undefined) { + qS += `&perPage=${perPage}`; + } + } else if (perPage !== undefined) { + qS += `?perPage=${perPage}`; + } + + return `${URL}${qS}`; +} + +export function getDataLength(dataState: any): Promise { + return fetch(buildUrl(dataState)) + .then((result) => result.json()) + .then((data) => data.length); +} +``` + + + +As Blazor Server is already a remote instance, unlike the demos in the other platforms we do not need to set another remote instance for the data, as the data is already remote. In order to do remote paging, we just need to set a couple of methods ins the data class + ```razor -BLAZOR CODE SNIPPET HERE + public Task> GetData(int index, int perPage) + { + var itemsToReturn = items.Skip(index).Take(perPage).ToList(); + return Task.FromResult(itemsToReturn); + } + + public Task GetDataLength() + { + return Task.FromResult(items.Count); + } +``` + + + + +```tsx +const URL = `https://data-northwind.indigo.design/`; + +export class RemoteService { + +public getData(dataState: any, index?: number, perPage?: number): any { + return fetch(this.buildUrl(dataState, index, perPage)) + .then((result) => result.json()); +} + +private buildUrl(dataState: any, index?: number, perPage?: number) { + let qS = ""; + if (dataState) { + qS += `${dataState.key}`; + } + + // Add index and perPage to the query string if they are defined + if (index !== undefined) { + qS += `?index=${index}`; + if (perPage !== undefined) { + qS += `&perPage=${perPage}`; + } + } else if (perPage !== undefined) { + qS += `?perPage=${perPage}`; + } + + return `${URL}${qS}`; +} + +public getDataLength(dataState: any): Promise { + return fetch(this.buildUrl(dataState)) + .then((result) => result.json()) + .then((data) => data.length); +} +} ``` + + After declaring the service, we need to create a component, which will be responsible for the `{ComponentName}` construction and data subscription. + ```typescript export class RemotePagingGridSample implements OnInit, AfterViewInit, OnDestroy { public data: Observable; @@ -603,13 +807,140 @@ export class RemotePagingGridSample implements OnInit, AfterViewInit, OnDestroy } } ``` + + + +First we need to bind to the relevant events so when we change pages and the amount of records shown per page, the remote service will fetch the correct amount of data +```ts +constructor() { + this._bind = () => { + this.pager.addEventListener("perPageChange", ()=> { + this.paginate(this.page); + }) + this.pager.addEventListener("pageChange", ((args: CustomEvent) => { + this.paginate(args.detail);}) as EventListener); + } + this._bind(); +} +``` +We also need to set the method for changing pages: +```ts +public paginate(page: number) { + this.page = page; + const skip = this.page * this.perPage; + const top = this.perPage; + + this.remotePagingService.getData(skip, top).then((data)=> { + this.data = data; // Assign received data to this.data + this.grid.isLoading = false; + this.updateUI(); // Update the UI after receiving data + }); +``` + +For further reference, please check the demo bellow: + +### Grid Remote Paging Demo + +`sample="/{ComponentSample}/remote-paging-grid", height="550", alt="{Platform} {ComponentTitle} Grid Remote Paging Example"` + + + + +First we should load some data to the grid. It is best to do after the grid has been rendered to avoid any timing issues. ```razor -BLAZOR CODE SNIPPET HERE + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await Paginate(0, PerPage); + totalRecordsCount = await NwindDataService.GetDataLength(); + StateHasChanged(); + } + } +``` +After that we just need to bind the paging events to our custom methods, and remote paging is set: + +```razor + + +.... + +@code { + private async void OnPerPageChange(IgbNumberEventArgs e) + { + PerPage = e.Detail; + await Paginate(0, e.Detail); + } + + private async void OnPageChange(IgbNumberEventArgs e) + { + await Paginate(e.Detail, PerPage); + } + ... + private async Task Paginate(double page, double perPage) + { + this.page = page; + double skip = this.page * PerPage; + double top = PerPage; + + try + { + data = await NwindDataService.GetData(Convert.ToInt32(skip), Convert.ToInt32(perPage)); + isLoading = false; + UpdateUI(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error fetching data: {ex.Message}"); + } + } +} +``` +For further reference please check the full demo bellow: + +### Grid Remote Paging Demo + +`sample="/{ComponentSample}/remote-paging-grid", height="550", alt="{Platform} {ComponentTitle} Grid Remote Paging Example"` + + + + +```tsx + paginate(evt.page)} + perPageChange={() => paginate(0)}> + ``` + +then set up the method: +```tsx + function paginate(pageArgs: number) { + page = pageArgs; + const skip = page * perPage; + const top = perPage; + + remoteServiceInstance.getData({ key: 'Customers' }, skip, top).then((incData:any)=> { + data = incData; + grid.current.isLoading = false; + grid.current.markForCheck();// Update the UI after receiving data + }); +``` +For further reference please check the full sample bellow: + +### Grid Remote Paging Demo + +`sample="/{ComponentSample}/remote-paging-grid", height="550", alt="{Platform} {ComponentTitle} Grid Remote Paging Example"` + + + + + ```typescript export class HGridRemotePagingSampleComponent implements OnInit, AfterViewInit, OnDestroy { public data: BehaviorSubject = new BehaviorSubject([]); @@ -633,13 +964,138 @@ export class HGridRemotePagingSampleComponent implements OnInit, AfterViewInit, } } ``` + + + +First we need to bind to the relevant events so when we change pages and the amount of records shown per page, the remote service will fetch the correct amount of data +```ts +constructor() { + this._bind = () => { + this.pager.addEventListener("perPageChange", ()=> { + this.paginate(this.page); + }) + this.pager.addEventListener("pageChange", ((args: CustomEvent) => { + this.paginate(args.detail);}) as EventListener); + } + this._bind(); +} +``` +We also need to set the method for changing pages: +```ts +public paginate(page: number) { + this.page = page; + const skip = this.page * this.perPage; + const top = this.perPage; + + this.remotePagingService.getData(skip, top).then((data)=> { + this.data = data; // Assign received data to this.data + this.grid.isLoading = false; + this.updateUI(); // Update the UI after receiving data + }); +``` + +For further reference, please check the demo bellow: + +### Grid Remote Paging Demo + +`sample="/{ComponentSample}/remote-paging-hgrid", height="550", alt="{Platform} {ComponentTitle} Hierarchical Grid Remote Paging Example"` + + + + +First we should load some data to the grid. It is best to do after the grid has been rendered to avoid any timing issues. + +```razor + protected override async Task OnAfterRenderAsync(bool firstRender) + { + if (firstRender) + { + await Paginate(0, PerPage); + totalRecordsCount = await NwindDataService.GetDataLength(); + StateHasChanged(); + } + } +``` +After that we just need to bind the paging events to our custom methods, and remote paging is set: ```razor -BLAZOR CODE SNIPPET HERE + + +.... + +@code { + private async void OnPerPageChange(IgbNumberEventArgs e) + { + PerPage = e.Detail; + await Paginate(0, e.Detail); + } + + private async void OnPageChange(IgbNumberEventArgs e) + { + await Paginate(e.Detail, PerPage); + } + ... + private async Task Paginate(double page, double perPage) + { + this.page = page; + double skip = this.page * PerPage; + double top = PerPage; + + try + { + data = await NwindDataService.GetData(Convert.ToInt32(skip), Convert.ToInt32(perPage)); + isLoading = false; + UpdateUI(); + } + catch (Exception ex) + { + Console.Error.WriteLine($"Error fetching data: {ex.Message}"); + } + } +} +``` +For further reference please check the full demo bellow: + +### Grid Remote Paging Demo + +`sample="/{ComponentSample}/remote-paging-grid", height="550", alt="{Platform} {ComponentTitle} Hierarchical Grid Remote Paging Example"` + + + + +```tsx + paginate(evt.page)} + perPageChange={() => paginate(0)}> + +``` +then set up the method: +```tsx + function paginate(pageArgs: number) { + page = pageArgs; + const skip = page * perPage; + const top = perPage; + + remoteServiceInstance.getData({ key: 'Customers' }, skip, top).then((incData:any)=> { + data = incData; + grid.current.isLoading = false; + grid.current.markForCheck();// Update the UI after receiving data + }); ``` +For further reference please check the full sample bellow: + +### Grid Remote Paging Demo + +`sample="/{ComponentSample}/remote-paging-hgrid", height="550", alt="{Platform} {ComponentTitle} Hierarchical Grid Remote Paging Example"` + + + + In this sample we will demonstrate how to display a certain number of root records per page no matter how many child records they have. In order to cancel the built-in Tree Grid paging algorithm, which displays a certain number of records no matter their level (root or child), we have to set the `PerPage` property to `Number.MAX_SAFE_INTEGER`. @@ -1009,7 +1465,6 @@ As you can see in the `Paginate` method, custom pagination logic is performed, b `sample="/{ComponentSample}/remote-paging-batch-editing", height="620", alt="{Platform} {ComponentTitle} Remote Paging Batch Editing Example"` - diff --git a/docfx/en/components/toc.json b/docfx/en/components/toc.json index 1d4b28156..2f3294094 100644 --- a/docfx/en/components/toc.json +++ b/docfx/en/components/toc.json @@ -477,7 +477,7 @@ "href": "grids/hierarchical-grid/paging.md" }, { - "exclude": ["Angular", "Blazor", "React", "WebComponents"], + "exclude": ["Angular"], "name": "Remote Data Operations", "href": "grids/hierarchical-grid/remote-data-operations.md" }, From efccf224bcf3977481873a7bf9d94279edbfff94 Mon Sep 17 00:00:00 2001 From: Mariela Tihova Date: Tue, 19 Nov 2024 18:06:23 +0200 Subject: [PATCH 2/2] Editing documentation with the latest changes on Remote Paging samples --- .../grids/_shared/remote-data-operations.md | 577 ++++++++++++------ 1 file changed, 399 insertions(+), 178 deletions(-) diff --git a/doc/en/components/grids/_shared/remote-data-operations.md b/doc/en/components/grids/_shared/remote-data-operations.md index e62a8e1a8..38ee9e898 100644 --- a/doc/en/components/grids/_shared/remote-data-operations.md +++ b/doc/en/components/grids/_shared/remote-data-operations.md @@ -536,43 +536,32 @@ export class RemotePagingService { ```ts export class RemotePagingService { - public remoteData: BehaviorSubject = new BehaviorSubject([]); - public dataLength: BehaviorSubject = new BehaviorSubject(0); - public url = 'https://www.igniteui.com/api/products'; + public static CUSTOMERS_URL = `https://data-northwind.indigo.design/Customers/GetCustomersWithPage`; + constructor() {} - constructor() {} - - public async getData(index?: number, perPage?: number): Promise { - let qS = ''; - - if (index !== undefined && perPage !== undefined) { - qS = `?$skip=${index}&$top=${perPage}&$count=true`; + public static getDataWithPaging(pageIndex?: number, pageSize?: number) { + return fetch(RemotePagingService.buildUrl(RemotePagingService.CUSTOMERS_URL, pageIndex, pageSize)) + .then((result) => result.json()) + .catch((error) => console.error(error.message)); } - - try { - const response = await fetch(`${this.url + qS}`); - if (!response.ok) { - throw new Error('Network response was not ok'); + + private static buildUrl(baseUrl: string, pageIndex?: number, pageSize?: number) { + let qS = ""; + if (baseUrl) { + qS += `${baseUrl}`; } - const data = await response.json(); - return data; - } catch (error) { - console.error('Error fetching data:', error); - throw error; // Propagate the error further - } -} -public async getDataLength(): Promise { - try { - const response = await fetch(this.url); - if (!response.ok) { - throw new Error('Network response was not ok'); + // Add pageIndex and size to the query string if they are defined + if (pageIndex !== undefined) { + qS += `?pageIndex=${pageIndex}`; + if (pageSize !== undefined) { + qS += `&size=${pageSize}`; + } + } else if (pageSize !== undefined) { + qS += `?perPage=${pageSize}`; } - const data = await response.json(); - return data.length; // Assuming the length is directly accessible in the JSON response - } catch (error) { - console.error('Error fetching data length:', error); - throw error; // Propagate the error further + + return `${qS}`; } } ``` @@ -598,39 +587,33 @@ As Blazor Server is already a remote instance, unlike the demos in the other pla ```tsx -const URL = `https://data-northwind.indigo.design/`; +const CUSTOMERS_URL = `https://data-northwind.indigo.design/Customers/GetCustomersWithPage`; export class RemoteService { -public getData(dataState: any, index?: number, perPage?: number): any { - return fetch(this.buildUrl(dataState, index, perPage)) + public static getDataWithPaging(pageIndex?: number, pageSize?: number) { + return fetch(this.buildUrl(CUSTOMERS_URL, pageIndex, pageSize)) .then((result) => result.json()); -} - -private buildUrl(dataState: any, index?: number, perPage?: number) { - let qS = ""; - if (dataState) { - qS += `${dataState.key}`; } - // Add index and perPage to the query string if they are defined - if (index !== undefined) { - qS += `?index=${index}`; - if (perPage !== undefined) { - qS += `&perPage=${perPage}`; + private static buildUrl(baseUrl: string, pageIndex?: number, pageSize?: number) { + let qS = ""; + if (baseUrl) { + qS += `${baseUrl}`; } - } else if (perPage !== undefined) { - qS += `?perPage=${perPage}`; - } - return `${URL}${qS}`; -} + // Add pageIndex and size to the query string if they are defined + if (pageIndex !== undefined) { + qS += `?pageIndex=${pageIndex}`; + if (pageSize !== undefined) { + qS += `&size=${pageSize}`; + } + } else if (pageSize !== undefined) { + qS += `?perPage=${pageSize}`; + } -public getDataLength(dataState: any): Promise { - return fetch(this.buildUrl(dataState)) - .then((result) => result.json()) - .then((data) => data.length); -} + return `${qS}`; + } } ``` @@ -680,42 +663,41 @@ export class RemotePagingService { ```ts -const URL = `https://data-northwind.indigo.design/`; - - +export class RemotePagingService { + public static BASE_URL = 'https://data-northwind.indigo.design/'; + public static CUSTOMERS_URL = `${RemotePagingService.BASE_URL}Customers/GetCustomersWithPage`; + + constructor() {} -export function getData(dataState: any, index?: number, perPage?: number): any { - return fetch(buildUrl(dataState, index, perPage)) + public static getDataWithPaging(pageIndex?: number, pageSize?: number) { + return fetch(RemotePagingService.buildUrl(RemotePagingService.CUSTOMERS_URL, pageIndex, pageSize)) + .then((result) => result.json()) + .catch((error) => console.error(error.message)); + } + + public static getHierarchyDataById(parentEntityName: string, parentId: string, childEntityName: string) { + return fetch(`${RemotePagingService.BASE_URL}${parentEntityName}/${parentId}/${childEntityName}`) .then((result) => result.json()); -} - -function buildUrl(dataState: any, index?: number, perPage?: number) { - let qS = ""; - if (dataState) { - if (dataState.rootLevel) { - qS += `${dataState.key}`; - } else { - qS += `${dataState.parentKey}/${dataState.parentID}/${dataState.key}`; - } } - // Add index and perPage to the query string if they are defined - if (index !== undefined) { - qS += `?index=${index}`; - if (perPage !== undefined) { - qS += `&perPage=${perPage}`; + private static buildUrl(baseUrl: string, pageIndex?: number, pageSize?: number) { + let qS = ""; + if (baseUrl) { + qS += `${baseUrl}`; } - } else if (perPage !== undefined) { - qS += `?perPage=${perPage}`; - } - return `${URL}${qS}`; -} + // Add pageIndex and size to the query string if they are defined + if (pageIndex !== undefined) { + qS += `?pageIndex=${pageIndex}`; + if (pageSize !== undefined) { + qS += `&size=${pageSize}`; + } + } else if (pageSize !== undefined) { + qS += `?perPage=${pageSize}`; + } -export function getDataLength(dataState: any): Promise { - return fetch(buildUrl(dataState)) - .then((result) => result.json()) - .then((data) => data.length); + return `${qS}`; + } } ``` @@ -740,39 +722,39 @@ As Blazor Server is already a remote instance, unlike the demos in the other pla ```tsx -const URL = `https://data-northwind.indigo.design/`; +const BASE_URL = `https://data-northwind.indigo.design/`; +const CUSTOMERS_URL = `${BASE_URL}Customers/GetCustomersWithPage`; export class RemoteService { -public getData(dataState: any, index?: number, perPage?: number): any { - return fetch(this.buildUrl(dataState, index, perPage)) + public static getCustomersDataWithPaging(pageIndex?: number, pageSize?: number) { + return fetch(this.buildUrl(CUSTOMERS_URL, pageIndex, pageSize)) .then((result) => result.json()); -} + } -private buildUrl(dataState: any, index?: number, perPage?: number) { - let qS = ""; - if (dataState) { - qS += `${dataState.key}`; + public static getHierarchyDataById(parentEntityName: string, parentId: string, childEntityName: string) { + return fetch(`${BASE_URL}${parentEntityName}/${parentId}/${childEntityName}`) + .then((result) => result.json()); } - // Add index and perPage to the query string if they are defined - if (index !== undefined) { - qS += `?index=${index}`; - if (perPage !== undefined) { - qS += `&perPage=${perPage}`; + private static buildUrl(baseUrl: string, pageIndex?: number, pageSize?: number) { + let qS = ""; + if (baseUrl) { + qS += `${baseUrl}`; } - } else if (perPage !== undefined) { - qS += `?perPage=${perPage}`; - } - return `${URL}${qS}`; -} + // Add pageIndex and size to the query string if they are defined + if (pageIndex !== undefined) { + qS += `?pageIndex=${pageIndex}`; + if (pageSize !== undefined) { + qS += `&size=${pageSize}`; + } + } else if (pageSize !== undefined) { + qS += `?perPage=${pageSize}`; + } -public getDataLength(dataState: any): Promise { - return fetch(this.buildUrl(dataState)) - .then((result) => result.json()) - .then((data) => data.length); -} + return `${qS}`; + } } ``` @@ -812,31 +794,60 @@ export class RemotePagingGridSample implements OnInit, AfterViewInit, OnDestroy First we need to bind to the relevant events so when we change pages and the amount of records shown per page, the remote service will fetch the correct amount of data ```ts -constructor() { - this._bind = () => { - this.pager.addEventListener("perPageChange", ()=> { - this.paginate(this.page); - }) - this.pager.addEventListener("pageChange", ((args: CustomEvent) => { - this.paginate(args.detail);}) as EventListener); - } - this._bind(); -} + constructor() { + this.grid = document.getElementById('grid') as IgcGridComponent; + this.pager = document.getElementById('paginator') as IgcPaginatorComponent; + + this._bind = () => { + window.addEventListener("load", () => { + this.loadData(this.page,this.perPage); + }); + + this.pager.addEventListener("perPageChange", ((args: CustomEvent) => { + this.perPage = args.detail; + this.loadData(this.page, this.perPage); + }) as EventListener); + + this.pager.addEventListener("pageChange", ((args: CustomEvent) => { + this.page = args.detail; + this.loadData(this.page, this.perPage); + }) as EventListener); + } + + this._bind(); + } ``` -We also need to set the method for changing pages: +We also need to set the method for loading data and update the UI accordingly: ```ts -public paginate(page: number) { - this.page = page; - const skip = this.page * this.perPage; - const top = this.perPage; + private loadData(pageIndex?: number, pageSize?: number): void { + this.grid.isLoading = true; - this.remotePagingService.getData(skip, top).then((data)=> { - this.data = data; // Assign received data to this.data - this.grid.isLoading = false; - this.updateUI(); // Update the UI after receiving data - }); + RemotePagingService.getDataWithPaging(pageIndex,pageSize) + .then((response: CustomersWithPageResponseModel) => { + this.totalRecordsCount = response.totalRecordsCount; + this.pager.perPage = pageSize; + this.pager.totalRecords = this.totalRecordsCount; + this.page = response.pageNumber; + this.data = response.items; + this.grid.isLoading = false; + this.updateUI(); // Update the UI after receiving data + }) + .catch((error) => { + console.error(error.message); + // Stop loading even if error occurs. Prevents endless loading + this.grid.isLoading = false; + this.updateUI(); + }) + } + + private updateUI(): void { + if (this.grid && this.data) { // Check if grid and data are available + this.grid.data = this.data; + } + } ``` + For further reference, please check the demo bellow: ### Grid Remote Paging Demo @@ -907,27 +918,66 @@ For further reference please check the full demo bellow: ```tsx - + paginate(evt.page)} - perPageChange={() => paginate(0)}> - + pageChange={onPageNumberChange} + perPageChange={onPageSizeChange}> + + + + + + + + +``` + +then set up the state: +```tsx + const grid = useRef(null); + const paginator = useRef(null); + const [data, setData] = useState([]); + const [page, setPage] = useState(0); + const [perPage, setPerPage] = useState(15); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + loadGridData(page, perPage); + }, [page, perPage]); ``` -then set up the method: +and finally set up the method for loading the data: ```tsx - function paginate(pageArgs: number) { - page = pageArgs; - const skip = page * perPage; - const top = perPage; - - remoteServiceInstance.getData({ key: 'Customers' }, skip, top).then((incData:any)=> { - data = incData; - grid.current.isLoading = false; - grid.current.markForCheck();// Update the UI after receiving data - }); + function loadGridData(pageIndex?: number, pageSize?: number) { + // Set loading state + setIsLoading(true); + + // Fetch data + RemoteService.getDataWithPaging(pageIndex, pageSize) + .then((response: CustomersWithPageResponseModel) => { + setData(response.items); + // Stop loading when data is retrieved + setIsLoading(false); + paginator.current.totalRecords = response.totalRecordsCount; + }) + .catch((error) => { + console.error(error.message); + setData([]); + // Stop loading even if error occurs. Prevents endless loading + setIsLoading(false); + }) + } ``` + For further reference please check the full sample bellow: ### Grid Remote Paging Demo @@ -969,29 +1019,101 @@ export class HGridRemotePagingSampleComponent implements OnInit, AfterViewInit, First we need to bind to the relevant events so when we change pages and the amount of records shown per page, the remote service will fetch the correct amount of data ```ts -constructor() { - this._bind = () => { - this.pager.addEventListener("perPageChange", ()=> { - this.paginate(this.page); - }) - this.pager.addEventListener("pageChange", ((args: CustomEvent) => { - this.paginate(args.detail);}) as EventListener); + constructor() { + this.hierarchicalGrid = document.getElementById("hGrid") as IgcHierarchicalGridComponent; + this.pager = document.getElementById('paginator') as IgcPaginatorComponent; + const ordersRowIsland = document.getElementById("ordersRowIsland") as IgcRowIslandComponent; + const orderDetailsRowIsland = document.getElementById("orderDetailsRowIsland") as IgcRowIslandComponent; + + ordersRowIsland.paginatorTemplate = this.webHierarchicalGridPaginatorTemplate; + orderDetailsRowIsland.paginatorTemplate = this.webHierarchicalGridPaginatorTemplate; + + this._bind = () => { + window.addEventListener("load", () => { + this.pager.perPage = this._perPage; + this.loadCustomersData(this.page,this.perPage); + }); + + this.pager.addEventListener("perPageChange", ((args: CustomEvent) => { + this.perPage = args.detail; + this.loadCustomersData(this.page, this.perPage); + }) as EventListener); + + this.pager.addEventListener("pageChange", ((args: CustomEvent) => { + this.page = args.detail; + this.loadCustomersData(this.page, this.perPage); + }) as EventListener); + + ordersRowIsland.addEventListener("gridCreated", (event: any) => { + this.gridCreated(event, "Customers"); + }); + + orderDetailsRowIsland.addEventListener("gridCreated", (event: any) => { + this.gridCreated(event, "Orders"); + }); + } + + this._bind(); } - this._bind(); -} ``` -We also need to set the method for changing pages: +We also need to set the method for loading data and update the UI accordingly: ```ts -public paginate(page: number) { - this.page = page; - const skip = this.page * this.perPage; - const top = this.perPage; - - this.remotePagingService.getData(skip, top).then((data)=> { - this.data = data; // Assign received data to this.data - this.grid.isLoading = false; + private updateUI(): void { + if (this.hierarchicalGrid && this.data) { // Check if grid and data are available + this.hierarchicalGrid.data = this.data; + } + } + + private loadCustomersData(pageIndex?: number, pageSize?: number): void { + this.hierarchicalGrid.isLoading = true; + + RemotePagingService.getDataWithPaging(pageIndex,pageSize) + .then((response: CustomersWithPageResponseModel) => { + this.totalRecordsCount = response.totalRecordsCount; + this.pager.perPage = pageSize; + this.pager.totalRecords = this.totalRecordsCount; + this.page = response.pageNumber; + this.data = response.items; + this.hierarchicalGrid.isLoading = false; this.updateUI(); // Update the UI after receiving data + }) + .catch((error) => { + console.error(error.message); + this.hierarchicalGrid.data = []; + this.hierarchicalGrid.isLoading = false; + this.updateUI(); + }) + } +``` + +And finally we need to handle the behaviour behind the actual hierarchy levels of the Hierarchical Gird +```ts + public gridCreated(event: CustomEvent, parentKey: string) { + const context = event.detail; + const parentId: string = context.parentID; + const childDataKey: string = context.owner.childDataKey; + + context.grid.isLoading = true; + RemotePagingService.getHierarchyDataById(parentKey, parentId, childDataKey) + .then((data: any) => { + context.grid.data = data; + context.grid.isLoading = false; + context.grid.markForCheck(); + }) + .catch((error) => { + console.error(error.message); + context.grid.data = []; + context.grid.isLoading = false; + context.grid.markForCheck(); }); + } + + public webHierarchicalGridPaginatorTemplate = () => { + return html ` + + ` + } ``` For further reference, please check the demo bellow: @@ -1064,31 +1186,130 @@ For further reference please check the full demo bellow: ```tsx - paginate(evt.page)} - perPageChange={() => paginate(0)}> - + + + + + + + + + + + gridCreated(rowIsland, e, "Customers")} + > + + + + + + + gridCreated(rowIsland, e, "Orders")} + > + + + + + + + +``` +then set up the state: +```tsx + const hierarchicalGrid = useRef(null); + const paginator = useRef(null); + + const [data, setData] = useState([]); + const [page, setPage] = useState(0); + const [perPage, setPerPage] = useState(15); + const [isLoading, setIsLoading] = useState(true); + + useEffect(() => { + loadGridData(page, perPage); + }, [page, perPage]); ``` -then set up the method: + +next set up the method for loading the data: ```tsx - function paginate(pageArgs: number) { - page = pageArgs; - const skip = page * perPage; - const top = perPage; + function loadGridData(pageIndex?: number, pageSize?: number) { + // Set loading state + setIsLoading(true); + + // Fetch data + RemoteService.getCustomersDataWithPaging(pageIndex, pageSize) + .then((response: CustomersWithPageResponseModel) => { + setData(response.items); + // Stop loading when data is retrieved + setIsLoading(false); + paginator.current.totalRecords = response.totalRecordsCount; + }) + .catch((error) => { + console.error(error.message); + setData([]); + // Stop loading even if error occurs. Prevents endless loading + setIsLoading(false); + }) + } +``` + - remoteServiceInstance.getData({ key: 'Customers' }, skip, top).then((incData:any)=> { - data = incData; - grid.current.isLoading = false; - grid.current.markForCheck();// Update the UI after receiving data - }); + + + + +and finally set up the behaviour for the RowIslands: + +```tsx + function gridCreated(rowIsland: IgrRowIsland, event: IgrGridCreatedEventArgs, parentKey: string) { + const context = event.detail; + const parentId: string = context.parentID; + const childDataKey: string = rowIsland.childDataKey; + + RemoteService.getHierarchyDataById(parentKey, parentId, childDataKey) + .then((data: any) => { + context.grid.data = data; + context.grid.isLoading = false; + context.grid.markForCheck(); + }) + .catch((error) => { + console.error(error.message); + context.grid.data = []; + context.grid.isLoading = false; + context.grid.markForCheck(); + }) + } ``` + + For further reference please check the full sample bellow: ### Grid Remote Paging Demo `sample="/{ComponentSample}/remote-paging-hgrid", height="550", alt="{Platform} {ComponentTitle} Hierarchical Grid Remote Paging Example"` +