UNPKG

imng-kendo-grid-odata

Version:

This library was generated with [Nx](https://nx.dev).

636 lines (627 loc) 29.1 kB
import * as i2 from 'rxjs'; import { BehaviorSubject, isObservable, first, map, withLatestFrom, take, switchMap, from, concatMap, tap, scan, last, merge, filter } from 'rxjs'; import * as i0 from '@angular/core'; import { InjectionToken, inject, Inject, Component, ChangeDetectorRef, Input, Directive, EventEmitter, Output, NgModule } from '@angular/core'; import { ODataService } from 'imng-kendo-odata'; import { KendoGridBaseComponent, hasHiddenColumns, ImngKendoGridModule } from 'imng-kendo-grid'; import * as i1 from '@angular/router'; import { isCompositeFilterDescriptor } from '@progress/kendo-data-query'; import { isCompositeFilter } from 'imng-odata-client'; import { map as map$1 } from 'rxjs/operators'; import { NgClass, AsyncPipe, CommonModule } from '@angular/common'; import { GridComponent, ColumnChooserComponent, PDFModule, ExcelModule } from '@progress/kendo-angular-grid'; import { Subscriptions } from 'imng-ngrx-utils'; import * as i4 from '@progress/kendo-angular-icons'; import { KENDO_SVGICON } from '@progress/kendo-angular-icons'; import * as i1$1 from '@progress/kendo-angular-buttons'; import { KENDO_BUTTON, KENDO_SPLITBUTTON } from '@progress/kendo-angular-buttons'; import { exportIcon, filePdfIcon, plusIcon, fileExcelIcon, filterClearIcon, arrowRotateCcwIcon } from '@progress/kendo-svg-icons'; import * as i2$1 from '@progress/kendo-angular-popup'; import { KENDO_POPUP } from '@progress/kendo-angular-popup'; import * as i3 from '@progress/kendo-angular-progressbar'; import { KENDO_PROGRESSBAR } from '@progress/kendo-angular-progressbar'; /* eslint-disable @angular-eslint/prefer-inject */ const FACADE = new InjectionToken('imng-grid-odata-facade'); const STATE = new InjectionToken('imng-grid-odata-odataState'); class KendoODataBasedComponent extends KendoGridBaseComponent { constructor(facade, state, router = null, //NOSONAR gridRefresh$ = null) { super(); this.facade = facade; this.state = state; this.router = router; this.gridRefresh$ = gridRefresh$; this.useLoadAllDataExport = false; this.odataService = inject(ODataService, { optional: true }); /** * This sets the amount of the maximum amount of sortable columns for this component. Default = 5. */ this.maxSortedColumnCount = 5; //NOSONAR this.loadDataProgression$ = new BehaviorSubject(0); this.gridStateQueryKey = 'odataState'; /** * Gets an Observable of all data for Excel export. * * Returns all data from the OData endpoint if the endpoint is available and * `useLoadAllDataExport` is enabled, otherwise returns the current grid data result. * * @returns {Observable<ODataResult<ENTITY>>} An Observable containing the OData result with entity data */ this.excelData = () => this.odataEndpoint && this.useLoadAllDataExport && this.odataService ? this.loadAllData() : this.gridDataResult$; if (this.router?.routerState?.snapshot?.root.queryParams[this.gridStateQueryKey]) { try { this.gridDataState = this.deserializeODataState(this.router?.routerState?.snapshot?.root?.queryParams[this.gridStateQueryKey]); } catch { console.error( //NOSONAR `Exception thrown while deserializing query string parameter: ${this.gridStateQueryKey}.`); } } if (isObservable(state)) { this.allSubscriptions.push(state.subscribe((t) => { this.gridDataState = t; this.expanders = t.expanders; this.compute = t.compute; this.transformations = t.transformations; }), state .pipe(first()) .subscribe((t) => (this.defaultFilter = t.filter))); } else { this.gridDataState = this.gridDataState ? { ...this.gridDataState, selectors: state.selectors, expanders: state.expanders, compute: state.compute, } : state; this.expanders = state.expanders; this.compute = state.compute; this.defaultFilter = state.filter; this.transformations = state.transformations; } if (gridRefresh$) { this.allSubscriptions.push(gridRefresh$.subscribe(() => this.loadEntities(this.gridDataState))); } } ngOnInit() { if (!this.gridRefresh$) { this.loadEntities(this.gridDataState); } this.loading$ = this.facade.loading$; this.gridDataResult$ = this.facade.gridData$?.pipe(map((gridData) => gridData ?? { total: 0, data: [] })); this.gridPagerSettings$ = this.facade.gridPagerSettings$; } deserializeODataState(stateQueryParam) { const state = JSON.parse(atob(stateQueryParam)); state.filter?.filters?.forEach((filter) => this.normalizeFilters(filter)); return state; } /** * This method ensures the proper handling of date filters in an OData query * @param filter */ normalizeFilters(filter) { if (isCompositeFilterDescriptor(filter) || isCompositeFilter(filter)) { filter.filters.forEach(this.normalizeFilters); } else { const filterObj = filter; const filterField = filterObj?.field?.toUpperCase(); if (filterField?.endsWith('DATE') || filterField?.endsWith('UTC')) { filter.value = new Date(filter.value); } } } serializeODataState(odataState) { return btoa(JSON.stringify(odataState)); } /** * Will reset filters to initialGrid state passed into the constructor */ resetFilters() { this.gridDataState = { ...this.gridDataState, filter: this.defaultFilter, }; if (!isObservable(this.state)) { this.gridDataState = { ...this.gridDataState, inFilters: this.state.inFilters, childFilters: this.state.childFilters, }; } this.loadEntities(this.gridDataState); } dataStateChange(state) { this.gridDataState = { ...state, expanders: this.expanders, compute: this.compute, transformations: this.transformations, filter: state.filter, }; this.loadEntities(this.gridDataState); } /** * Loads all data from the OData service by fetching data in chunks of 100 items. * * This method retrieves the current grid data and OData state, then creates multiple * OData queries to fetch all available data in batches. Each batch is limited to 100 items * to manage memory and performance. The results from all batches are accumulated and returned * as a single ODataResult. * * @returns {Observable<ODataResult<ENTITY>>} An observable that emits the complete accumulated result * containing the total count and combined data from all fetched batches. After emission, * sets the useLoadAllDataExport flag to false. * * @remarks * - Uses `concatMap` to ensure requests are processed sequentially * - Uses `scan` to accumulate results from each batch * - Count is disabled on subsequent requests (count: false) to optimize performance * - The useLoadAllDataExport flag is reset to false upon completion */ loadAllData() { return this.facade.gridData$.pipe(withLatestFrom(this.facade.gridODataState$), take(1), map(([data, state]) => ({ total: data?.total ?? 0, state: state })), map(({ total, state }) => { if (!state?.take || total <= state.take) { return { totalRecordCount: total, queries: [state] }; } const odataQueries = []; const totalRecordCount = total; while (total > 0) { odataQueries.push({ ...state, skip: odataQueries.length * 100, take: 100, count: false, // we don't need the count on subsequent requests }); total -= 100; } return { totalRecordCount: totalRecordCount, queries: odataQueries }; }), switchMap((queryData) => from(queryData.queries).pipe(concatMap((odataQuery) => (this.odataService ?? new ODataService()) .fetch(this.odataEndpoint ?? '', odataQuery ?? { skip: 0, take: 100 }) .pipe(tap(() => { this.loadDataProgression$.next(Math.max(1, Math.trunc(((odataQuery?.skip ?? 0) / queryData.totalRecordCount) * 100))); }))), scan((accumulated, current) => ({ total: queryData.totalRecordCount, data: [...accumulated.data, ...current.data], })), last())), tap(() => { this.useLoadAllDataExport = false; this.loadDataProgression$.next(0); })); } loadEntities(odataState) { odataState = this.validateSortParameters(odataState); this.gridDataState = odataState; this.expanders = odataState.expanders; this.compute = odataState.compute; this.transformations = odataState.transformations; this.facade.loadEntities(this.gridDataState); this.updateRouterState(odataState); } validateSortParameters(state) { if (state.sort && (state.sort?.length || 0) > this.maxSortedColumnCount) { state = { ...state, sort: state.sort.slice(0, this.maxSortedColumnCount), }; console.warn(`You have exceeded the limit of ${this.maxSortedColumnCount} sorted columns for the current grid. MAX-Sorted-Column-Count`); //NOSONAR } return state; } updateRouterState(state) { if (this.router) { const tempState = { ...state }; delete tempState.selectors; delete tempState.expanders; delete tempState.compute; this.router.navigate([], { relativeTo: this.router.routerState.root, queryParams: { [this.gridStateQueryKey]: this.serializeODataState(tempState), }, skipLocationChange: false, queryParamsHandling: 'merge', }); } } reloadEntities() { this.facade.reloadEntities(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: KendoODataBasedComponent, deps: [{ token: FACADE }, { token: STATE }, { token: i1.Router }, { token: i2.Observable }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "21.2.10", type: KendoODataBasedComponent, isStandalone: true, selector: "ng-component", usesInheritance: true, ngImport: i0, template: '', isInline: true }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: KendoODataBasedComponent, decorators: [{ type: Component, args: [{ template: '', }] }], ctorParameters: () => [{ type: undefined, decorators: [{ type: Inject, args: [FACADE] }] }, { type: undefined, decorators: [{ type: Inject, args: [STATE] }] }, { type: i1.Router }, { type: i2.Observable }] }); const getODataPagerSettings = (m) => { if (!m.gridODataState || !m.gridODataState.take || !m.gridData || !m.gridData.total) { return false; } let pageCount = m.gridData.total / m.gridODataState.take; pageCount = Math.min(10, Math.ceil(pageCount)); return { buttonCount: pageCount, info: true, pageSizes: [10, 20, 50, 100], previousNext: true, type: 'numeric', }; }; const mapPagerSettings = () => (source) => source.pipe(map$1((m) => getODataPagerSettings(m))); function createKendoODataGridInitialState() { return { gridData: { data: [], total: 0 }, loading: false, gridODataState: {}, gridPagerSettings: false, error: undefined }; } class IMNG_KENDO_GRID_ODATA { constructor() { this.gridComponent = inject(GridComponent); this.changeDetectorRef = inject(ChangeDetectorRef); this.allSubscriptions = new Subscriptions(); } ngOnInit() { this.facade = this.odataComponent.facade || {}; this.gridComponent.reorderable = true; this.gridComponent.resizable = true; this.gridComponent.filterable = 'menu'; this.gridComponent.sortable = { allowUnsort: true, mode: 'multiple', }; this.gridComponent.navigable = true; this.allSubscriptions.push(this.facade.loading$.subscribe((t) => { this.gridComponent.loading = t; this.changeDetectorRef.markForCheck(); })); this.odataComponent.hasHiddenColumns$ = merge(this.odataComponent.facade.loading$.pipe(hasHiddenColumns(this.gridComponent)), this.gridComponent.columnVisibilityChange?.pipe(hasHiddenColumns(this.gridComponent))); } ngAfterViewInit() { this.allSubscriptions.push(this.gridComponent.dataStateChange.subscribe((t) => this.odataComponent.dataStateChange(t)), this.facade.gridData$.subscribe((t) => { this.gridComponent.data = t || []; this.changeDetectorRef.markForCheck(); }), this.facade.gridPagerSettings$.subscribe((t) => (this.gridComponent.pageable = t)), this.facade.gridODataState$.pipe(filter((t) => !!t)).subscribe((t) => { this.gridComponent.pageSize = t?.take || 20; //NOSONAR this.gridComponent.filter = t?.filter || { logic: 'and', filters: [], }; this.gridComponent.skip = t?.skip || 0; this.gridComponent.sort = t?.sort || []; })); } ngOnDestroy() { this.allSubscriptions.unsubscribeAll(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: IMNG_KENDO_GRID_ODATA, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "21.2.10", type: IMNG_KENDO_GRID_ODATA, isStandalone: true, selector: "[imngODataGrid]", inputs: { odataComponent: ["imngODataGrid", "odataComponent"] }, ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: IMNG_KENDO_GRID_ODATA, decorators: [{ type: Directive, args: [{ selector: '[imngODataGrid]', }] }], propDecorators: { odataComponent: [{ type: Input, args: ['imngODataGrid'] }] } }); class IMNG_KENDO_GRID_ODATA_HEADER { constructor() { this.parentGrid = inject(GridComponent); this.exportIcon = exportIcon; this.filePdfIcon = filePdfIcon; this.plusIcon = plusIcon; this.fileExcelIcon = fileExcelIcon; this.filterClearIcon = filterClearIcon; this.arrowRotateCcwIcon = arrowRotateCcwIcon; this.entityName = ''; this.hideColumnChooser = false; this.hideResetFilters = false; this.hideReloadData = false; this.hideExports = false; this.addItemClicked = new EventEmitter(); this.resetFiltersClicked = new EventEmitter(); this.reloadEntitiesClicked = new EventEmitter(); } ngOnInit() { this.exportOptions = [ { name: 'Export PDF', command: 'pdf', click: () => this.parentGrid.saveAsPDF(), svgIcon: filePdfIcon, }, { name: 'Export Excel', command: 'excel', click: () => this.parentGrid.saveAsExcel(), svgIcon: fileExcelIcon, }, ]; if (this.imngODataGrid.odataService && this.imngODataGrid.odataEndpoint) { this.exportOptions.push({ name: 'Export All Excel', command: 'excel', click: () => this.configureGridForLoadAllData((grid) => grid.saveAsExcel()), svgIcon: fileExcelIcon, }); } this.loadDataProgression$ = this.imngODataGrid.loadDataProgression$; } configureGridForLoadAllData(exportCallback) { this.imngODataGrid.loadDataProgression$.next(1); this.imngODataGrid.useLoadAllDataExport = true; exportCallback(this.parentGrid); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: IMNG_KENDO_GRID_ODATA_HEADER, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "21.2.10", type: IMNG_KENDO_GRID_ODATA_HEADER, isStandalone: true, selector: "imng-kendo-grid-odata-header", inputs: { imngODataGrid: "imngODataGrid", entityName: "entityName", hideColumnChooser: "hideColumnChooser", hideResetFilters: "hideResetFilters", hideReloadData: "hideReloadData", hideExports: "hideExports", hasHiddenColumns$: "hasHiddenColumns$" }, outputs: { addItemClicked: "addItemClicked", resetFiltersClicked: "resetFiltersClicked", reloadEntitiesClicked: "reloadEntitiesClicked" }, ngImport: i0, template: ` <span #popupAnchor class="k-w-full k-justify-content-center"></span> @if (loadDataProgression$ | async; as loadDataProgression) { <kendo-popup class="w-25" [anchor]="popupAnchor" [anchorAlign]="{ horizontal: 'center', vertical: 'center', }" [popupAlign]="{ horizontal: 'center', vertical: 'center', }"> <div class="text-center"> @if (loadDataProgression > 0 && loadDataProgression <= 5) { <div class="font-weight-bold">Initializing...</div> } @else if (loadDataProgression > 5 && loadDataProgression < 90) { <div class="font-weight-bold">Loading Data...</div> } @else if (loadDataProgression >= 90) { <div class="font-weight-bold">Almost There...</div> } <div> <kendo-progressbar [value]="loadDataProgression" [min]="0" [max]="100" [label]="{ visible: true, format: 'percent', position: 'center', }"></kendo-progressbar> </div> </div> </kendo-popup> } <div class="mr-5 pr-5"> @if (entityName) { <button name="imngAddEntity" type="button" title="Add {{ entityName }}" primary="true" (click)="addItemClicked.emit()" class="btn btn-sm btn-primary mx-1 imng-grid-odata-hdr-btn"> <kendo-svg-icon [icon]="plusIcon"></kendo-svg-icon> Add {{ entityName }} </button> } @if (hideResetFilters !== true) { <button name="imngResetFilters" type="button" title="Reset Filters" (click)="resetFiltersClicked.emit()" class="btn btn-sm mx-1 imng-grid-odata-hdr-btn"> <kendo-svg-icon [icon]="filterClearIcon"></kendo-svg-icon> Reset Filters </button> } @if (hideReloadData !== true) { <button name="imngReloadData" type="button" title="Clear Cache And Reload Data" (click)="reloadEntitiesClicked.emit()" class="btn btn-sm mx-1 imng-grid-odata-hdr-btn"> <kendo-svg-icon [icon]="arrowRotateCcwIcon"></kendo-svg-icon> Reload Data </button> } @if (hideExports !== true) { <kendo-splitbutton [data]="exportOptions" [svgIcon]="exportIcon" textField="name" class="btn btn-sm mx-1 imng-grid-odata-hdr-btn"> Export Data </kendo-splitbutton> } @if (hideColumnChooser !== true) { <kendo-grid-column-chooser name="imngColumnChooser" title="Columns" [allowHideAll]="true" [autoSync]="true" [ngClass]="{ 'text-primary': (hasHiddenColumns$ | async), }" /> } </div>`, isInline: true, styles: [".btn-sm{height:30px;border-radius:2px;background-color:#f5f5f5;border-color:#00000014}.btn-primary{background-color:#007bff}.k-icon{padding-bottom:3px}.k-bare{border-color:#00000014!important;background-color:#f5f5f5!important;background-image:linear-gradient(#0000,#00000005)!important}\n"], dependencies: [{ kind: "directive", type: NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "component", type: i1$1.SplitButtonComponent, selector: "kendo-splitbutton", inputs: ["text", "icon", "svgIcon", "iconClass", "type", "imageUrl", "size", "rounded", "fillMode", "themeColor", "disabled", "popupSettings", "tabIndex", "textField", "data", "arrowButtonClass", "arrowButtonIcon", "arrowButtonSvgIcon", "buttonAttributes"], outputs: ["buttonClick", "itemClick", "focus", "blur", "open", "close"], exportAs: ["kendoSplitButton"] }, { kind: "component", type: i2$1.PopupComponent, selector: "kendo-popup", inputs: ["animate", "anchor", "anchorAlign", "collision", "popupAlign", "copyAnchorStyles", "popupClass", "positionMode", "offset", "margin"], outputs: ["anchorViewportLeave", "close", "open", "positionChange"], exportAs: ["kendo-popup"] }, { kind: "component", type: i3.ProgressBarComponent, selector: "kendo-progressbar", inputs: ["label", "progressCssStyle", "progressCssClass", "emptyCssStyle", "emptyCssClass", "animation"], outputs: ["animationEnd"], exportAs: ["kendoProgressBar"] }, { kind: "component", type: i4.SVGIconComponent, selector: "kendo-svg-icon, kendo-svgicon", inputs: ["icon"], exportAs: ["kendoSVGIcon"] }, { kind: "component", type: ColumnChooserComponent, selector: "kendo-grid-column-chooser", inputs: ["autoSync", "filterable", "showSelectAll", "allowHideAll"] }, { kind: "pipe", type: AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: IMNG_KENDO_GRID_ODATA_HEADER, decorators: [{ type: Component, args: [{ selector: 'imng-kendo-grid-odata-header', imports: [ AsyncPipe, NgClass, KENDO_BUTTON, KENDO_SPLITBUTTON, KENDO_POPUP, KENDO_PROGRESSBAR, KENDO_SVGICON, ColumnChooserComponent, ], template: ` <span #popupAnchor class="k-w-full k-justify-content-center"></span> @if (loadDataProgression$ | async; as loadDataProgression) { <kendo-popup class="w-25" [anchor]="popupAnchor" [anchorAlign]="{ horizontal: 'center', vertical: 'center', }" [popupAlign]="{ horizontal: 'center', vertical: 'center', }"> <div class="text-center"> @if (loadDataProgression > 0 && loadDataProgression <= 5) { <div class="font-weight-bold">Initializing...</div> } @else if (loadDataProgression > 5 && loadDataProgression < 90) { <div class="font-weight-bold">Loading Data...</div> } @else if (loadDataProgression >= 90) { <div class="font-weight-bold">Almost There...</div> } <div> <kendo-progressbar [value]="loadDataProgression" [min]="0" [max]="100" [label]="{ visible: true, format: 'percent', position: 'center', }"></kendo-progressbar> </div> </div> </kendo-popup> } <div class="mr-5 pr-5"> @if (entityName) { <button name="imngAddEntity" type="button" title="Add {{ entityName }}" primary="true" (click)="addItemClicked.emit()" class="btn btn-sm btn-primary mx-1 imng-grid-odata-hdr-btn"> <kendo-svg-icon [icon]="plusIcon"></kendo-svg-icon> Add {{ entityName }} </button> } @if (hideResetFilters !== true) { <button name="imngResetFilters" type="button" title="Reset Filters" (click)="resetFiltersClicked.emit()" class="btn btn-sm mx-1 imng-grid-odata-hdr-btn"> <kendo-svg-icon [icon]="filterClearIcon"></kendo-svg-icon> Reset Filters </button> } @if (hideReloadData !== true) { <button name="imngReloadData" type="button" title="Clear Cache And Reload Data" (click)="reloadEntitiesClicked.emit()" class="btn btn-sm mx-1 imng-grid-odata-hdr-btn"> <kendo-svg-icon [icon]="arrowRotateCcwIcon"></kendo-svg-icon> Reload Data </button> } @if (hideExports !== true) { <kendo-splitbutton [data]="exportOptions" [svgIcon]="exportIcon" textField="name" class="btn btn-sm mx-1 imng-grid-odata-hdr-btn"> Export Data </kendo-splitbutton> } @if (hideColumnChooser !== true) { <kendo-grid-column-chooser name="imngColumnChooser" title="Columns" [allowHideAll]="true" [autoSync]="true" [ngClass]="{ 'text-primary': (hasHiddenColumns$ | async), }" /> } </div>`, styles: [".btn-sm{height:30px;border-radius:2px;background-color:#f5f5f5;border-color:#00000014}.btn-primary{background-color:#007bff}.k-icon{padding-bottom:3px}.k-bare{border-color:#00000014!important;background-color:#f5f5f5!important;background-image:linear-gradient(#0000,#00000005)!important}\n"] }] }], propDecorators: { imngODataGrid: [{ type: Input, args: [{ required: true }] }], entityName: [{ type: Input }], hideColumnChooser: [{ type: Input }], hideResetFilters: [{ type: Input }], hideReloadData: [{ type: Input }], hideExports: [{ type: Input }], hasHiddenColumns$: [{ type: Input }], addItemClicked: [{ type: Output }], resetFiltersClicked: [{ type: Output }], reloadEntitiesClicked: [{ type: Output }] } }); class ImngKendoGridODataModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ImngKendoGridODataModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "21.2.10", ngImport: i0, type: ImngKendoGridODataModule, imports: [CommonModule, PDFModule, ExcelModule, ImngKendoGridModule, IMNG_KENDO_GRID_ODATA, IMNG_KENDO_GRID_ODATA_HEADER], exports: [IMNG_KENDO_GRID_ODATA, IMNG_KENDO_GRID_ODATA_HEADER] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ImngKendoGridODataModule, imports: [CommonModule, PDFModule, ExcelModule, ImngKendoGridModule, IMNG_KENDO_GRID_ODATA_HEADER] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "21.2.10", ngImport: i0, type: ImngKendoGridODataModule, decorators: [{ type: NgModule, args: [{ imports: [ CommonModule, PDFModule, ExcelModule, ImngKendoGridModule, IMNG_KENDO_GRID_ODATA, IMNG_KENDO_GRID_ODATA_HEADER, ], exports: [IMNG_KENDO_GRID_ODATA, IMNG_KENDO_GRID_ODATA_HEADER], }] }] }); /** * Generated bundle index. Do not edit. */ export { IMNG_KENDO_GRID_ODATA, IMNG_KENDO_GRID_ODATA_HEADER, ImngKendoGridODataModule, KendoODataBasedComponent, createKendoODataGridInitialState, getODataPagerSettings, mapPagerSettings }; //# sourceMappingURL=imng-kendo-grid-odata.mjs.map