# Enabling Virtualization

## Content

## Enabling data virtualization with RestCollectionView

<span style="color: rgb(23, 43, 77); font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: -0.08px; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: pre-wrap; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">Virtualization is an effective method for handling massive datasets by virtualizing data requests. This functionality is especially handy when dealing with huge collections, as loading all data at once would be inefficient. By extending </span>`RestCollectionView`<span style="color: rgb(23, 43, 77); font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: -0.08px; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: pre-wrap; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;"> class, we can create a custom class called </span>`VirtualRestCollectionView `<span style="color: rgb(23, 43, 77); font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: -0.08px; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: pre-wrap; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">and set the </span>`virtualization `<span style="color: rgb(23, 43, 77); font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: -0.08px; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: pre-wrap; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">property to true, allowing us to interface with the data source and load data in chunks.</span>

#### **Supported operations**

* Virtualization: Efficiently fetches data in chunks as needed, reducing memory usage and improving performance.
* Server-Side Filtering and Sorting: Applies filters and sorting on the server side, ensuring only the required data is retrieved.

> type=info
> This feature is supported for FlexGrid, FlexSheet, MultiRow.

## Extending RestCollectionView

For virtualization feature, we'll need to initialize our variables and override `getItems` method to fetch data on demand.

```auto
import { RestCollectionView } from '@mescius/wijmo.rest';
import {copy,httpRequest,asNumber} from "@mescius/wijmo";

export class VirtualRestCollectionView extends RestCollectionView{
    _url: string;
     /**
     * 
     * @param url: The endpoint URL for the REST API.
     * @param options: Optional configuration parameters that can be passed during instantiation.
     */
    constructor(url, options?) {
        super();
        this.groupOnServer = false;
        this.virtualization = true;
        this._url = url;
        copy(this, options);
    }
}
```

<span style="color: rgb(23, 43, 77); font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: -0.08px; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: pre-wrap; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">The data received from Sever contains the dates in string format and to convert them to JavaScript Dates objects, we require the JSON Revier method.</span>

```auto
// parse data
    protected _jsonReviver(key: string, value: any): any {
        const _rxDate = /^\d{4}\-\d{2}\-\d{2}T\d{2}\:\d{2}\:\d{2}|\/Date\([\d\-]*?\)/;
        if (typeof value === 'string' && _rxDate.test(value)) {
            value = value.indexOf('/Date(') == 0 // verbosejson
                ? new Date(parseInt(value.substr(6)))
                : new Date(value);
        }
        return value;
    }
```

Before making the request to the server to retrieve the data, we must prepare the request parameters. To do this, we would write the `_getReadParams` method with the following parameters:

* **Filtering**: Converts the filter criteria into OData format and applies it to the request.
* **Sorting**: Constructs an order-by clause based on the sorting descriptions.
* **Virtualization**: Adds `skip` and `top` parameters to the request for efficient data pagination.

```auto
_getReadParams(): any {
        let settings: any = {};
        // apply filter 
        if (this.filterOnServer && this._filterProvider) {
            let filter = this._asODataFilter(this._filterProvider);
            if (filter.length > 0) {
                settings.filterBy = filter;
            }
        }
        //apply orderBy
        if (this.sortDescriptions.length > 0) {
            let _sortBy = [];
            for (let i = 0; i < this.sortDescriptions.length; i++) {
                let sort = `${this.sortDescriptions[i].property} ${this.sortDescriptions[i].ascending ? 'ASC' : 'DESC'}`;
                _sortBy.push(sort);// add sort
            }
            settings.orderBy = _sortBy.join(',');
        }
        // 
        if (this.virtualization) {
            settings.skip = this._start;
            settings.top = this._fetchSize();
        }
        return settings;
    }
```

> type=info
> The filters are converted to OData format using the \_asODataFilter function. If your data source does not support ODataFormat, you can create your custom method to transform the filter query to the data source's acceptable format.

`_asODataFilter` method code can be get from [RestCollectionView\OData Demo](https://developer.mescius.com/wijmo/demos/Core/CollectionView/RestCollectionView/OData/purejs "https://developer.mescius.com/wijmo/demos/Core/CollectionView/RestCollectionView/OData/purejs") sample’s rest-collection-view-odata.js file
As the request parameters are ready, now we are ready to send the request to the Server to fetch the data. For this, `getItems` method would be override.

```auto
protected getItems(): Promise<any[]> {
        // cancel any pending requests
        if (this._pendingReq) {
            this._pendingReq.abort();
        }
        return new Promise<any>(resolve => {
            let _settings = this._getReadParams(); // get the items virtually 
            this._pendingReq = httpRequest(this._url, {
                requestHeaders: this.requestHeaders,
                data: _settings,
                success: async xhr => {
                    // parse response
                    let resp = JSON.parse(xhr.responseText, this._jsonReviver);
                    let _count = asNumber(resp.totalItemCount);
                    if (_count != this._totalItemCount)
                        this._totalItemCount = _count;
                    resolve(resp.items);
                },
                error: xhr => this._raiseError(xhr.responseText, false),
                complete: xhr => { this._pendingReq = null; }// no pending requests
            });
        });;
    }
```

<span style="color: rgb(23, 43, 77); font-family: -apple-system, BlinkMacSystemFont, Segoe UI, Roboto, Oxygen, Ubuntu, Fira Sans, Droid Sans, Helvetica Neue, sans-serif; font-size: 16px; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: -0.08px; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; white-space: pre-wrap; background-color: rgb(255, 255, 255); text-decoration-thickness: initial; text-decoration-style: initial; text-decoration-color: initial; display: inline !important; float: none;">Now, we're able to call the RESTCollectionView in our JavaScript file and use that as our data source for your FlexGrid control:</span>

```auto
// Extended RESTCollectionView class
import { VirtualRestCollectionView } from './virtual-rest-collection-view';
import { FlexGrid } from '@mescius/wijmo.grid';
function init(){
  let cv =  new VirtualRestCollectionView(url); // create CollectionView Instance
  let grid = new FlexGrid("#virtualGrid", {
        autoGenerateColumns: false,
        columns: [
            { binding: 'productId', header: 'Product ID', width: '*' },
            { binding: 'color', header: 'Color', width: '*' },
            { binding: 'modifiedDate', header: 'Modified Date', dataType: 'Date', format: 'd' },
            { binding: 'quantity', header: 'Quantity', dataType: 'Number', format: 'n2' },
            { binding: 'actualCost', header: 'Actual Cost', dataType: 'Number', format: 'n2'}
        ],
        itemsSource:cv // assign Custom Collection View Instance
    });
}
```

> type=note
> Note: Pagination is not supported

You can check a sample implementation with server and client code **[Wijmo-Rest-CollectionView-Sample](https://github.com/wijmo/Wijmo-Rest-CollectionView-Sample)**