UNPKG

@revolist/revogrid

Version:

Virtual reactive data grid spreadsheet component - RevoGrid.

105 lines (104 loc) 4.35 kB
/*! * Built by Revolist OU ❤️ */ import reduce from "lodash/reduce"; import { isRowType, rowTypes, DataStore, getSourceItem, getVisibleSourceItem, } from "../store/index"; /** * Data source provider * * @dependsOn DimensionProvider */ export class DataProvider { constructor(dimensionProvider) { this.dimensionProvider = dimensionProvider; this.stores = reduce(rowTypes, (sources, k) => { sources[k] = new DataStore(k); return sources; }, {}); } /** * Replaces the data source for a row type and synchronizes the related dimension metadata. * * `rgRow` updates also refresh the virtual row model unless `disableVirtualRows` is set. * Pinned row types skip virtual row recalculation because they are rendered directly. * * @param data Full source data assigned to the target row store. * @param type Row collection to update. Defaults to the main body rows. * @param disableVirtualRows Prevents recalculating virtual rows for the main row store. * @param grouping Optional grouping metadata applied together with the new data set. * @param silent Preserves the current trimmed state instead of resetting it during the update. * @param preserveTrimmed Re-applies current trimmed indexes after a silent update. * @returns The same `data` array that was provided to the method. */ setData(data, type = 'rgRow', disableVirtualRows = false, grouping, // if true, store will be updated without resetting trimmed state silent = false, preserveTrimmed = false) { // set rgRow data this.stores[type].updateData([...data], grouping, silent, preserveTrimmed); // for pinned row no need virtual data const noVirtual = type !== 'rgRow' || disableVirtualRows; this.dimensionProvider.setData(data.length, type, noVirtual); return data; } getModel(virtualIndex, type = 'rgRow') { const store = this.stores[type].store; return getSourceItem(store, virtualIndex); } changeOrder({ rowType = 'rgRow', from, to }) { const storeService = this.stores[rowType]; // take currently visible row indexes const newItemsOrder = [...storeService.store.get('proxyItems')]; const prevItems = storeService.store.get('items'); // take out const toMove = newItemsOrder.splice(newItemsOrder.indexOf(prevItems[from]), // get index in proxy 1); // insert before newItemsOrder.splice(newItemsOrder.indexOf(prevItems[to]), // get index in proxy 0, ...toMove); storeService.setData({ proxyItems: newItemsOrder, }); // take currently visible row indexes const newItems = storeService.store.get('items'); this.dimensionProvider.updateSizesPositionByNewDataIndexes(rowType, newItems, prevItems); } setCellData({ type, rowIndex, prop, val }, mutate = true) { const model = this.getModel(rowIndex, type); model[prop] = val; this.stores[type].setSourceData({ [rowIndex]: model }, mutate); } setRangeData(data, type) { const items = {}; for (let rowIndex in data) { const oldModel = (items[rowIndex] = getSourceItem(this.stores[type].store, parseInt(rowIndex, 10))); if (!oldModel) { continue; } for (let prop in data[rowIndex]) { oldModel[prop] = data[rowIndex][prop]; } } this.stores[type].setSourceData(items); } refresh(type = 'all') { if (isRowType(type)) { this.refreshItems(type); } rowTypes.forEach((t) => this.refreshItems(t)); } refreshItems(type = 'rgRow') { const items = this.stores[type].store.get('items'); this.stores[type].setData({ items: [...items] }); } setGrouping({ depth }, type = 'rgRow') { this.stores[type].setData({ groupingDepth: depth }); } setTrimmed(trimmed, type = 'rgRow') { const store = this.stores[type]; store.addTrimmed(trimmed); this.dimensionProvider.setTrimmed(trimmed, type); if (type === 'rgRow') { this.dimensionProvider.setData(getVisibleSourceItem(store.store).length, type); } } }