UNPKG

sdk-datagrid

Version:

Customizable (Angular) datagrid with data options for manipulation, and charts for visualization.

728 lines (611 loc) 30.3 kB
<img src="https://www.soodohkohd.com/assets/images/logo.png" title="soo-doh-kohd" height="200"/> ## Description: The sdk-datagrid component is a mobile-friendly, fully-functional data grid that gives the developer complete control over the processing and appearance of the data. From a simple table to a complex, customizable (Excel-like) spreadsheet, this component adds so much power to any application. ## Angular Compatibility Chart | Version | Compatibility | |---------|---------------| | 16 | EOL 2025 | | 17 | EOL 2025 | | 18 | | | 19 | | | 20 | Q3 2025 | **NOTE: This package leverages the [sdk-core-library](https://www.npmjs.com/package/sdk-core-library) for core configurations (i.e., colors, icons, etc.).** ## INSTALLATION: Using NPM: ```bash npm install --save sdk-datagrid ``` ## CONFIGURATION: To configure the ```sdk-datagrid``` for your application, add the following lines to your app.module.ts file: ```typescript import { SDKDatagridModule } from 'sdk-datagrid'; @NgModule({ imports: [ SDKDatagridModule ] }) export class AppModule { } ``` ## PROPERTIES: ```typescript /************************************************************************** * Input/Output Parameters for updating the Grid **************************************************************************/ @Input() updateGrid: boolean = false; // Applies changes/data to the grid. @Output() updateGridChange = new EventEmitter<boolean>(); // Callback to set updateGrid variable. /************************************************************************** * Input/Output Parameters for editing a record **************************************************************************/ @Input() editRecordIndex: number | null | undefined; // The record that is currently being edited. @Output() editRecordIndexChange = new EventEmitter<number | null | undefined>(); // Callback to set editRecordIndex variable. /************************************************************************** * Input/Output Parameters for dataset change **************************************************************************/ @Input() datasets: string[] = []; // List of datasets. @Input() activeDataset: string = ""; // The current selected dataset. @Output() activeDatasetChange = new EventEmitter<string>(); // Callback to set activeDataset variable. /************************************************************************** * Input/Output Parameters for updating columns **************************************************************************/ @Input() columns: SDKDataGridColumn[] = []; // The columns to be used for the grid. @Input() columnHeaderStyle: string = ""; // Style used for column headers. @Output() columnsChange = new EventEmitter<SDKDataGridColumn[]>(); // Callback to set columns variable. /************************************************************************** * Input Parameters for rows **************************************************************************/ @Input() detailTemplate!: TemplateRef<any>; // Embedded component for row detail. @Input() tooltipTemplate!: TemplateRef<any>; // Tooltip for row. /************************************************************************** * Input/Output Parameters for updating custom filters **************************************************************************/ @Input() customFilters: SDKDataGridCustomFilter[] = []; // Custom filters added to standard filter provided in loaddata callback (filters). @Output() customFiltersChange = new EventEmitter<SDKDataGridCustomFilter[]>(); // Callback to set custom filters variable. /************************************************************************** * Input/Output Parameters for exporting data **************************************************************************/ @Input() dataExport: any = ""; // The data to export. @Output() dataExportChange = new EventEmitter<any>(); // Callback to set dataExport variable. /************************************************************************** * Input/Output Parameters for settings data **************************************************************************/ @Input() settings: SDKDataGridSettings[] = []; // Options that are saved outside the grid. This value should be set to the value retieved from the datagrid @Output method "settingsSavedEvent". Consider it a passthrough value. @Input() clearSettingsCache: boolean = false; // Clears any grid storage of settings. @Output() savedSettingsEvent: EventEmitter<SDKDataGridSettings[]> = new EventEmitter(); // Used as a callback to save settings. @Output() clearSettingsCacheChange = new EventEmitter<boolean>(); // Callback to set clearSettingsCache variable. /************************************************************************** * Required Output Parameters **************************************************************************/ @Output() loadDataEvent = new EventEmitter<any>(); // Callback with grid changes. /************************************************************************** * Optional Input/Output Parameters **************************************************************************/ @Input() name: string = ""; // Unique name of the grid (per page). @Input() title: string = ""; // Title of the grid. @Input() titleStyle: string = ""; // Style used for title. @Input() options: SDKDataGridOptions | undefined; // Grid options. @Input() fontFamily: string = ""; // font-family used for grid. @Input() data: any = ""; // The data to display in the grid. @Input() rowValues: number[] = [10, 25, 50, 100, 500, 1000]; // Sets the values used for records per page. @Input() defaultRows: number = 100; // Default value for records per page. @Input() rows: number | undefined; // Current rows in dataset. @Input() page: number | undefined; // Current page of dataset. @Input() total: number | undefined; // Total records in dataset. @Output() saveGridDataEvent: EventEmitter<any> = new EventEmitter(); // Callback for saving changes to data. @Output() deleteGridDataEvent: EventEmitter<any> = new EventEmitter(); // Callback for saving changes to data. @Output() selectedRowActionEvent: EventEmitter<any> = new EventEmitter(); // // Callback for row actions. NOTE: The return object is { record: [the record], index: [the record index] } /************************************************************************** * Processing Parameters **************************************************************************/ @Input() error: string = ""; // Any errors that occur during processing. @Input() isDebug: boolean = false; // Turns on debugging. ``` ## USAGE: ### Basic Setup ```html <sdk-datagrid [(updateGrid)]="updateGrid" [(columns)]="columns" [data]="data" [rows]="rows" [page]="page" [total]="total" [error]="error" (loadDataEvent)="loadData($event)"> </sdk-datagrid> ``` ### .ts file ```typescript public updateGrid: boolean = false; // Required 2-way binding. public columns: SDKDataGridColumn[] = []; // Required 2-way binding. public data: any; public rows: number | undefined; public page: number | undefined; public total: number | undefined; public error: string = ""; // Callback function for loading data (required). public async loadData(event: any = null) { this.isLoading = true; let body: string = this.buildBody(event); try { await this.httpService.Post(dataSource, body).then((data: any) => { if (data) { this.data = data["Data"]; this.rows = parseInt(data["Rows"]); this.page = parseInt(data["Page"]); this.total = parseInt(data["Total"]); this.error = data["Error"]; setTimeout(() => { this.updateGrid = true; // Tell the grid to update. }, 100); } }); } catch (error: any) { this.error = error.message; } this.isLoading = false; } // Change the body parameters to fit your API call. private buildBody(event: any = null): string { let sorts: any = []; let filters: any = []; let formulas: any = []; this.column.forEach((column: SDKDataGridColumn) => { if (column.Sort) { sorts.push({ ColumnName: column.Name, Direction: column.Sort.direction, Position: column.Sort.position }); } if (column.Filter) { let filtersOperation = Object.keys(Filters)[Object.values(Filters).indexOf(column.Filter.operation[0].toString())]; filters.push({ ColumnName: column.Name, Operation: filtersOperation, Value: column.Filter.value }); } if (column.Formulas) { let formulaOperation = Object.keys(FormulaOperation)[Object.values(FormulaOperation).indexOf(column.Formulas.operation.toString())]; formulas.push({ ColumnName: column.Name, Operation: formulaOperation, Format: column.Formulas.format }); } }); let parameters: any = { rows: event.rows, page: event.page, sorts: sorts, filters: filters, formulas: formulas }; return JSON.stringify(parameters); } ``` ### Columns If you want to specify the columns, define them using the ```SDKDataGridColumn``` object. #### .ts file ```typescript @ViewChild('category') category!: TemplateRef<any>; @ViewChild('dataTemplate') dataTemplate!: TemplateRef<any>; @ViewChild('actionRight') actionRight!: TemplateRef<any>; @ViewChild('detailTemplate') detailTemplate!: TemplateRef<any>; public updateGrid: boolean = false; public editRecordIndex: number | null | undefined = null; public columns: SDKDataGridColumn[] = [ { Name: 'category', DisplayName: 'Category', required: true, style: 'color: red', notes: 'MUST be a valid Category.', editTemplate: () => this.category }, { Name: 'air_date', DisplayName: 'Date', required: true, validCharacters: 'calendar', pattern: 'YYYY-MM-DD' }, { Name: 'question', DisplayName: 'Question', isVisible: false, height: '50px', width: '100px', dataTemplate: () => this.dataTemplate }, { Name: 'value', DisplayName: 'Value', required: true, notes: 'Between 100 - 1000.', validCharacters: 'numeric' }, { Name: 'answer', DisplayName: 'Answer', dataTemplate: () => this.dataTemplate }, { Name: 'round', DisplayName: 'Round' }, { Name: 'show_number', DisplayName: 'Show', validCharacters: 'custom', pattern: '^[0-9]{4}$' }, { Name: 'fin', DisplayName: 'Completed' }, { Name: 'Edit', DisplayName: 'Edit', dataTemplate: () => this.actionRight } ]; public data: any; public rows: number | undefined; public page: number | undefined; public total: number | undefined; public error: string = ""; // If editing is enabled... public editData(index: any) { this.editRecordIndex = index; } public saveData(index: number, record: any) { // Update the record as a whole. let dataIndex = ((this.page ?? 1) - 1) * (this.rows ?? 0) + index; this.data[dataIndex] = { ...record }; // Update each column in the record. for (let key in this.data[dataIndex]) { if (Object.prototype.hasOwnProperty.call(activeRow, key)) { this.data[index][key] = record[key]; } } // Save to database and show message. // Reload data. } public cancelData() { this.editRecordIndex = null; this.updateGrid = true; // Tell grid to update. } ``` #### .html file ```html <sdk-datagrid [(updateGrid)]="updateGrid" [(columns)]="columns" [(editRecordIndex)]="editRecordIndex" [data]="data" [rows]="rows" [page]="page" [total]="total" [error]="error" [detailTemplate]="detailTemplate" [tooltipTemplate]="tooltipTemplate" (loadDataEvent)="loadData($event)"> </sdk-datagrid> <ng-template #category let-index="index" let-record="record"> <div> <select style="margin-left: 10px;"> <option value="">...</option> <option value="HISTORY">HISTORY</option> <option value="3-LETTER WORDS">3-LETTER WORDS</option> <option value="THE COMPANY LINE">THE COMPANY LINE</option> <option value="EPITAPHS & TRIBUTES">EPITAPHS & TRIBUTES</option> <option value="ESPN's TOP 10 ALL-TIME ATHLETES">ESPN's TOP 10 ALL-TIME ATHLETES</option> </select> </div> </ng-template> <ng-template #dataTemplate let-value="value"> <div>{{ value }}</div> </ng-template> <ng-template #actionRight let-index="index" let-record="record" let-column="column" let-value="value"> <div *ngIf="index !== editRecordIndex"> <div title="Edit" class="icon cursor" (click)="editData(index)">edit</div> <div title="Delete" class="icon cursor delete">delete</div> </div> <div *ngIf="index === editRecordIndex"> <div title="Save" class="icon cursor done" (click)="saveData(index, record)">done</div> <div title="Cancel" class="icon cursor delete" (click)="cancelData()">close</div> </div> </ng-template> <ng-template #detailTemplate let-index="index" let-record="record"> <div style="color: blue; cursor: pointer;">{{ record["question"] }}</div> </ng-template> <ng-template #tooltipTemplate let-index="index" let-record="record"> <div style="color: blue; cursor: pointer; max-height: 300px; max-width: 200px; overflow: auto;">Round: {{ record["round"] }}</div> </ng-template> ``` ### Exporting Data ```html <sdk-datagrid [(updateGrid)]="updateGrid" [(columns)]="columns" [(dataExport)]="dataExport" [data]="data" [rows]="rows" [page]="page" [total]="total" [error]="error" (loadDataEvent)="loadData($event)"> </sdk-datagrid> ``` ### .ts file ```typescript public updateGrid: boolean = false; // Required 2-way binding. public columns: SDKDataGridColumn[] = []; // Required 2-way binding. public dataExport: any; // Required 2-way binding for exporting. public data: any; public rows: number | undefined; public page: number | undefined; public total: number | undefined; public error: string = ""; // Callback function for loading data (required). public async loadData(event: any = null) { this.isLoading = true; let body: string = this.buildBody(event); // The "event" will contain "Export Data" ONLY if the "Include all data" option has // been selected in the Export window. If so, this indicates you want to export ALL // your data without filtering or sorting. Basically, clearing out the "body" parameter // removes the filtering and sorting requirements. If that option is NOT selected, // the exporting is handled within the sdk-datagrid based on the current "data" value. if (event && event.action === "Export Data") { body = ""; } try { await this.httpService.Post(dataSource, body).then((data: any) => { if (data) { if (event && event.action === "Export Data") { this.dataExport = data["Data"]; this.isLoading = false; } else { this.data = data["Data"]; this.rows = parseInt(data["Rows"]); this.page = parseInt(data["Page"]); this.total = parseInt(data["Total"]); this.error = data["Error"]; setTimeout(() => { this.updateGrid = true; // Tell the grid to update. }, 100); } } }); } catch (error: any) { this.error = error.message; } this.isLoading = false; } // Change the body parameters to fit your API call. private buildBody(event: any = null): string { let sorts: any = []; let filters: any = []; let formulas: any = []; this.column.forEach((column: SDKDataGridColumn) => { if (column.Sort) { sorts.push({ ColumnName: column.Name, Direction: column.Sort.direction, Position: column.Sort.position }); } if (column.Filter) { let filtersOperation = Object.keys(Filters)[Object.values(Filters).indexOf(column.Filter.operation[0].toString())]; filters.push({ ColumnName: column.Name, Operation: filtersOperation, Value: column.Filter.value }); } if (column.Formulas) { let formulaOperation = Object.keys(FormulaOperation)[Object.values(FormulaOperation).indexOf(column.Formulas.operation.toString())]; formulas.push({ ColumnName: column.Name, Operation: formulaOperation, Format: column.Formulas.format }); } }); let parameters: any = { rows: event.rows, page: event.page, sorts: sorts, filters: filters, formulas: formulas }; return JSON.stringify(parameters); } ``` ### Custom Options If you want to add a custom option to the ```sdk-datagrid```, use the ```optionAddons/windowAddons``` parameters. First, create your "custom" option and window components. #### mycustom-option.component #### .html file ```html <div (click)="showDataOptions('myCustom')"> <div title="My Custom Option" class="sdk-icon" [ngClass]="optionTitle === 'myCustom' ? 'active' : ''">file_download</div> <div *ngIf="myCustomBadge !== ''" class="badge"> <div class="label">{{ myCustomBadge }}</div> </div> </div> ``` #### .ts file ```typescript import { Component, EventEmitter, Input, Output } from '@angular/core'; @Component({ selector: 'mycustom-option', templateUrl: './mycustom-option.component.html', styleUrls: ['./mycustom-option.component.scss'] }) export class MyCustomOptionComponent { @Input() optionTitle: string = ""; // Unique name for option. @Output() showDataOptionsEvent = new EventEmitter<any>(); // Method to show option window. public myCustomBadge: string = ""; // Used to add badge to custom option. public showDataOptions(type: string) { this.showDataOptionsEvent.emit(type); } } ``` #### mycustom-window.component #### .html file ```html <div *ngIf="dataClass === 'expand' && optionTitle === 'mycustom'" class="sdk-datagrid-window"> <div class="header"> <span class="title">My Custom Option</span> <span title="Close" class="sdk-icon close" (click)="close()">close</span> </div> <div class="actions"> // Add your custom actions here (if applicable). </div> <div class="content"> // Add your custom option functionality here. </div> <div class="footer"> <button class="button" type="button" (click)="apply()">Apply</button> </div> </div> ``` #### .ts file ```typescript import { Component, EventEmitter, Input, Output } from '@angular/core'; import { SDKDataGridColumn } from 'sdk-datagrid'; @Component({ selector: 'mycustom-window', templateUrl: './mycustom-window.component.html', styleUrls: ['./mycustom-window.component.scss'] }) export class MyCustomWindowComponent { @Input() dataClass: string = ""; // Used to indicate if window is open/closed. @Input() optionTitle: string = ""; // Unique name for option. @Input() datasets: any[] = []; // Data array. @Input() columns: SDKDataGridColumn[] = []; // Columns defines for data. @Input() filters: any[] = []; // Filters defines for data. @Input() sorts: any[] = []; // Sorting defines for data. @Output() applyEvent = new EventEmitter<any>(); // Apply option. @Output() closeEvent = new EventEmitter<any>(); // Close window. public close() { this.closeEvent.emit(); } public async apply() { this.applyEvent.emit(); this.closeEvent.emit(); } } ``` Then add those components to your datagrid. #### .ts file ```typescript import { MyCustomOptionComponent } from './mycustom/option/mycustom-option.component'; import { MyCustomWindowComponent } from './mycustom/window/mycustom-window.component'; public myCustomOptionComponent = MyCustomOptionComponent; public myCustomWindowComponent = MyCustomWindowComponent; ``` #### .html file ```html <sdk-datagrid [(updateGrid)]="updateGrid" [(columns)]="columns" [data]="data" [rows]="rows" [page]="page" [total]="total" [optionAddons]="[myCustomOptionComponent]" [windowAddons]="[myCustomWindowComponent]" [error]="error" (loadDataEvent)="loadData($event)"> </sdk-datagrid> ``` ### (Alternative) Custom Options ```typescript private observer: MutationObserver | null = null; public ngAfterViewInit() { let observerCallback: MutationCallback = (mutations) => { for (let mutation of mutations) { if (mutation.type === 'childList') { let optionsLabel = document.querySelector("div[title='Data Options'].label-title"); if (optionsLabel) { // Custom option let option = document.createElement('div'); option.setAttribute('title', 'My Custom Option'); option.setAttribute('class', 'sdk-icon'); option.textContent = 'for_you'; // This is the Materials icon text option.addEventListener('click', () => { console.log("Option has been clicked!"); }); let postion = 1; // the position in the list (1 - n) or 0 (place at the end) let options = Array.from(optionsLabel.parentNode!.querySelectorAll('.icons .option')); let referenceElement = options[(postion ?? 0) - 1]; let lastOption = options[options.length - 1]; if (referenceElement) { // Insert before the reference element optionsLabel.parentNode!.insertBefore(option, referenceElement); } else { // Add to the end if reference element not found optionsLabel.parentNode!.insertBefore(option, lastOption.nextSibling); } this.observer?.disconnect(); // Stop observing once the option has been added break; } } } }; this.observer = new MutationObserver(observerCallback); this.observer.observe(document.body, { childList: true, subtree: true }); } public ngOnDestroy(): void { this.observer?.disconnect(); // Cleanup the observer when the component is destroyed } ``` ### NOTES: - In order to update the grid, you MUST set the ```updateGrid``` property to ```true```. The grid will automatically set it back to ```false``` once the update is complete (hence the 2-way binding). - To customize filtering for a column: Define the ```FilterTypes``` and ```FilterValues``` in the columns object. ```typescript public columns: SDKDataGridColumn[] = [ { Name: 'category', DisplayName: 'Category', required: true, style: 'color: red', notes: 'MUST be a valid Category.', editTemplate: () => this.category }, { Name: 'air_date', DisplayName: 'Date', required: true, validCharacters: 'calendar', pattern: 'YYYY-MM-DD' }, { Name: 'question', DisplayName: 'Question', height: '50px', width: '100px', dataTemplate: () => this.dataTemplate }, { Name: 'value', DisplayName: 'Value', required: true, notes: 'Between 100 - 1000.', validCharacters: 'numeric' }, { Name: 'answer', DisplayName: 'Answer', dataTemplate: () => this.dataTemplate }, { Name: 'round', DisplayName: 'Round', FilterTypes: [ Filters.Equals ], FilterValues: [ 'Jeopardy!', 'Double Jeopardy!' ] }, { Name: 'show_number', DisplayName: 'Show', FilterTypes: [ Filters.LessThanOrEqual, Filters.GreaterThanOrEqual ], FilterValues: [ 4000, 4500, 5000 ], validCharacters: 'custom', pattern: '^[0-9]{4}$' }, { Name: 'fin', DisplayName: 'Completed', FilterTypes: [ Filters.Equals ], FilterValues: [ true, false ] }, { Name: 'Edit', DisplayName: 'Edit', actionSide: "right", dataTemplate: () => this.actionRight } ]; ``` To use a multi-select dropdown as your filter, define the ```FilterMultiSelect``` and ```FilterValues``` in the columns object. ```typescript public columns: SDKDataGridColumn[] = [ { Name: 'category', DisplayName: 'Category', required: true, style: 'color: red', notes: 'MUST be a valid Category.', editTemplate: () => this.category }, { Name: 'air_date', DisplayName: 'Date', required: true, validCharacters: 'calendar', pattern: 'YYYY-MM-DD' }, { Name: 'question', DisplayName: 'Question', isVisible: false, height: '50px', width: '100px', dataTemplate: () => this.dataTemplate }, { Name: 'value', DisplayName: 'Value', required: true, notes: 'Between 100 - 1000.', validCharacters: 'numeric' }, { Name: 'answer', DisplayName: 'Answer', showSort: false, showFilter: false, dataTemplate: () => this.dataTemplate }, { Name: 'round', DisplayName: 'Round', FilterMultiSelect: true, FilterValues: [ 'Jeopardy!', 'Double Jeopardy!', 'Final Jeopardy!', 'Tiebreaker' ] }, { Name: 'show_number', DisplayName: 'Show', FilterTypes: [ Filters.GreaterThanOrEqual, Filters.LessThanOrEqual ], FilterValues: [ 4000, 4500, 5000, 6000 ] }, { Name: 'fin', DisplayName: 'Completed', FilterTypes: [ Filters.Equals ], FilterValues: [ true, false ]}, { Name: 'Edit', DisplayName: 'Edit', actionSide: "right", dataTemplate: () => this.actionRight } ]; ``` - To create custom filters (```SDKDataGridCustomFilter```), the following properties are available: ```typescript public Name: string = ""; // Unique filter name. public DisplayName?: string = ""; // Name to display to user. public Type?: FilterType = FilterType.Textbox; // Type of filter (Textbox, TextboxOnly, Checkbox, Dropdown). public notes?: string = ""; // START: sdk-select properties for Dropdown filters. public FilterMultiSelect?: boolean = false; // Allows multiple filter values to be selected. public FilterTypes?: any[] = []; // Allows you to define specific filter types. NOTE: If FilterMultiSelect = true, this property is forced to [Filters.Equals, Filters.NotEquals]. public FilterValues?: any[] = []; // Allows you to define specific filter values. public Filter?: SDKDataGridFilter | null = null; // Values set for filter. public FilterValueDefault?: any; // Default value for Dropdown type. public setFilterValues?: () => Promise<any[]>; // Optional callback method to load filter values. // END: sdk-select properties for Dropdown filters. FilterType Enums: - Textbox - TextboxOnly - Checkbox - Dropdown ``` **NOTE:** If ```Type = FilterType.Textbox``` and is used with ```FilterTypes```, the custom filter will have an Operation/Value layout. If ```FilterTypes``` is NOT used, the layout will ONLY have a Value. - To use columns (```SDKDataGridColumn```), the following properties are available: ```typescript public Name: string = ""; // Original db name. public DisplayName?: string = ""; // System override of db name (Name). public FriendlyName?: string = ""; // User provides. Produces * indicator. public Sort?: SDKDataGridSort | null = null; // Sorting (asc/desc) applied to column data. public Filter?: SDKDataGridFilter | null = null; // Filters applied to column data. public Formulas?: any = null; // Formulas applied to column. public showSort?: boolean = true; // Allows you to turn on/off sorting capabilities. public showFilter?: boolean = true; // Allows you to turn on/off filtering capabilities. public isAction?: boolean = false; // Is the column associated to an action. public isVisible?: boolean = true; // Allows you to turn on/off the visibility of the column. public actionSide?: string = "right" // right or left public dataStyle?: string = "" // Used to apply styles to the data element. public formulaStyle?: string = "" // Used to apply styles to the formula element. // START: Filter properties public FilterMultiSelect?: boolean = false; // Allows multiple filter values to be selected. public FilterTypes?: any[] = []; // Allows you to define specific filter types. NOTE: If FilterMultiSelect = true, this property is forced to [Filters.Equals, Filters.NotEquals]. public FilterValues?: any[] = []; // Allows you to define specific filter values. public FilterType?: FilterType = FilterType.Textbox; // Type of filter (Textbox, TextboxOnly, Checkbox, Dropdown). public FilterValueDefault?: any; // Default value for Dropdown type. // END: Filter properties // START: editTemplate option public allowEdit?: boolean = true; public required?: boolean = false; public notes?: string = ""; public validCharacters?: string = ""; public hint?: string = ""; public pattern?: string = ""; public height?: string = ""; public width?: string = ""; public border?: string = ""; public style?: string = ""; // END: editTemplate option // Custom templates public headerTemplate?: () => TemplateRef<any>; public dataTemplate?: () => TemplateRef<any>; public editTemplate?: () => TemplateRef<any>; // Custom methods public formatData?: (value: any) => string; // Optional callback method to format the data. public setFilterValues?: () => Promise<any[]>; // Optional callback method to load filter values. ``` - To use options (```SDKDataGridOptions```), the following properties are available: ```typescript public header?: boolean = true; public footer?: boolean = true; public paging?: boolean = true; public options?: boolean = true; public datasetTabs?: boolean = false; public autoClosePanel?: boolean = true; public minimizeOptions?: boolean = false; public expandableRows?: boolean = false; public settings?: boolean = false; public columns?: boolean = true; public filters?: boolean = true; public sorts?: boolean = true; public formulas?: boolean = true; public charts?: boolean = false; public export?: boolean = true; public edit?: boolean = false; public delete?: boolean = true; public nowrap?: boolean = false; public settingsStorage?: StorageType = StorageType.Local; ```