UNPKG

@syncfusion/ej2-grids

Version:

Feature-rich JavaScript datagrid (datatable) control with built-in support for editing, filtering, grouping, paging, sorting, and exporting to Excel.

654 lines (653 loc) 30 kB
import { isNullOrUndefined, extend } from '@syncfusion/ej2-base'; import { Query, DataManager, Predicate, Deferred, UrlAdaptor, RemoteSaveAdaptor } from '@syncfusion/ej2-data'; import { setFormatter, isGroupAdaptive, getColumnByForeignKeyValue, refreshFilteredColsUid } from '../base/util'; import * as events from '../base/constant'; import { ValueFormatter } from '../services/value-formatter'; import { CheckBoxFilterBase } from '../common/checkbox-filter-base'; /** * Grid data module is used to generate query and data source. * * @hidden */ var Data = /** @class */ (function () { /** * Constructor for data module. * * @param {IGrid} parent - specifies the IGrid * @param {ServiceLocator} serviceLocator - specifies the service locator * @hidden */ function Data(parent, serviceLocator) { this.dataState = { isPending: false, resolver: null, group: [] }; this.foreignKeyDataState = { isPending: false, resolver: null }; this.parent = parent; this.serviceLocator = serviceLocator; this.initDataManager(); if (this.parent.isDestroyed || this.getModuleName() === 'foreignKey') { return; } this.parent.on(events.rowsAdded, this.addRows, this); this.parent.on(events.rowPositionChanged, this.reorderRows, this); this.parent.on(events.rowsRemoved, this.removeRows, this); this.parent.on(events.dataSourceModified, this.initDataManager, this); this.parent.on(events.destroy, this.destroy, this); this.parent.on(events.updateData, this.crudActions, this); this.parent.on(events.addDeleteAction, this.getData, this); this.parent.on(events.autoCol, this.refreshFilteredCols, this); this.parent.on(events.columnsPrepared, this.refreshFilteredCols, this); } Data.prototype.reorderRows = function (e) { if (this.parent.isRemote()) { this.parent.getCurrentViewRecords().splice(e.toIndex, 0, this.parent.getCurrentViewRecords().splice(e.fromIndex, 1)[0]); } else { this.dataManager.dataSource.json.splice(e.toIndex, 0, this.dataManager.dataSource.json.splice(e.fromIndex, 1)[0]); } }; Data.prototype.getModuleName = function () { return 'data'; }; /** * The function used to initialize dataManager and external query * * @returns {void} */ Data.prototype.initDataManager = function () { var gObj = this.parent; this.dataManager = gObj.dataSource instanceof DataManager ? gObj.dataSource : (isNullOrUndefined(gObj.dataSource) ? new DataManager() : new DataManager(gObj.dataSource)); if (gObj.isAngular && !(gObj.query instanceof Query)) { gObj.setProperties({ query: new Query() }, true); } else { this.isQueryInvokedFromData = true; if (!(gObj.query instanceof Query)) { gObj.query = new Query(); } } }; /** * Generates a query based on the current grid configuration. * * @param {boolean} skipPage - If `true`, the query will exclude paging information. * @param {boolean} skipGroup - If `true`, the query will exclude grouping information. * * @returns {Query} A query object reflecting the current grid state. */ Data.prototype.generateQuery = function (skipPage, skipGroup) { var gObj = this.parent; var query = !isNullOrUndefined(gObj.getQuery()) ? gObj.getQuery().clone() : new Query(); if (this.parent.columnQueryMode === 'ExcludeHidden') { query.select(this.parent.getColumns().filter(function (column) { return !(column.isPrimaryKey !== true && column.visible === false || column.field === undefined); }).map(function (column) { return column.field; })); } else if (this.parent.columnQueryMode === 'Schema') { var selectQueryFields = []; var columns = this.parent.columns; for (var i = 0; i < columns.length; i++) { selectQueryFields.push(columns[parseInt(i.toString(), 10)].field); } query.select(selectQueryFields); } this.filterQuery(query); this.searchQuery(query); this.aggregateQuery(query); this.sortQuery(query); if (isGroupAdaptive(this.parent)) { this.virtualGroupPageQuery(query); } else { this.pageQuery(query, skipPage); } if (isNullOrUndefined(skipGroup) || !skipGroup) { this.groupQuery(query); } return query; }; /** * @param {Query} query - specifies the query * @returns {Query} - returns the query * @hidden */ Data.prototype.aggregateQuery = function (query) { var rows = this.parent.aggregates; for (var i = 0; i < rows.length; i++) { var row = rows[parseInt(i.toString(), 10)]; for (var j = 0; j < row.columns.length; j++) { var cols = row.columns[parseInt(j.toString(), 10)]; var types = cols.type instanceof Array ? cols.type : [cols.type]; for (var k = 0; k < types.length; k++) { query.aggregate(types[parseInt(k.toString(), 10)].toLowerCase(), cols.field); } } } return query; }; Data.prototype.virtualGroupPageQuery = function (query) { var fName = 'fn'; if (query.queries.length) { for (var i = 0; i < query.queries.length; i++) { if (query.queries[parseInt(i.toString(), 10)]["" + fName] === 'onPage') { query.queries.splice(i, 1); } } } return query; }; Data.prototype.pageQuery = function (query, skipPage) { var gObj = this.parent; if (skipPage) { return query; } var fName = 'fn'; var args = { query: query, skipPage: false }; gObj.notify(events.setVirtualPageQuery, args); if (args.skipPage) { return query; } if ((gObj.allowPaging || gObj.enableVirtualization || gObj.enableInfiniteScrolling) && skipPage !== true) { gObj.pageSettings.currentPage = Math.max(1, gObj.pageSettings.currentPage); if (gObj.pageSettings.pageCount <= 0) { gObj.pageSettings.pageCount = 8; } if (gObj.pageSettings.pageSize <= 0) { gObj.pageSettings.pageSize = 12; } if (query.queries.length) { for (var i = 0; i < query.queries.length; i++) { if (query.queries[parseInt(i.toString(), 10)]["" + fName] === 'onPage') { query.queries.splice(i, 1); } } } if (!isNullOrUndefined(gObj.infiniteScrollModule) && gObj.enableInfiniteScrolling) { this.parent.notify(events.infinitePageQuery, query); } else { query.page(gObj.pageSettings.currentPage, gObj.allowPaging && gObj.pagerModule && (gObj.pagerModule.pagerObj.isAllPage && !gObj.isManualRefresh) && (!this.dataManager.dataSource.offline && !(this.dataManager.adaptor instanceof RemoteSaveAdaptor)) ? null : gObj.pageSettings.pageSize); } } return query; }; Data.prototype.groupQuery = function (query) { var gObj = this.parent; if (gObj.allowGrouping && gObj.groupSettings.columns.length) { if (this.parent.groupSettings.enableLazyLoading) { query.lazyLoad.push({ key: 'isLazyLoad', value: this.parent.groupSettings.enableLazyLoading }); } var columns = gObj.groupSettings.columns; for (var i = 0, len = columns.length; i < len; i++) { var column = this.getColumnByField(columns[parseInt(i.toString(), 10)]); if (!column) { this.parent.log('initial_action', { moduleName: 'group', columnName: columns[parseInt(i.toString(), 10)] }); } var isGrpFmt = column.enableGroupByFormat; var format = column.format; if (isGrpFmt) { query.group(columns[parseInt(i.toString(), 10)], this.formatGroupColumn.bind(this), format); } else { query.group(columns[parseInt(i.toString(), 10)], null); } } } return query; }; Data.prototype.sortQuery = function (query) { var gObj = this.parent; if ((gObj.allowSorting || gObj.allowGrouping) && gObj.sortSettings.columns.length) { var columns = gObj.sortSettings.columns; var sortGrp = []; for (var i = columns.length - 1; i > -1; i--) { var col = this.getColumnByField(columns[parseInt(i.toString(), 10)].field); if (col) { col.setSortDirection(columns[parseInt(i.toString(), 10)].direction); } else { this.parent.log('initial_action', { moduleName: 'sort', columnName: columns[parseInt(i.toString(), 10)].field }); return query; } var fn = columns[parseInt(i.toString(), 10)].direction; if (col.sortComparer) { this.parent.log('grid_sort_comparer'); fn = !this.isRemote() ? col.sortComparer.bind(col) : columns[parseInt(i.toString(), 10)].direction; } if (gObj.groupSettings.columns.indexOf(columns[parseInt(i.toString(), 10)].field) === -1) { if (col.isForeignColumn() || col.sortComparer) { query.sortByForeignKey(col.field, fn, undefined, columns[parseInt(i.toString(), 10)].direction.toLowerCase()); } else { query.sortBy(col.field, fn); } } else { sortGrp.push({ direction: fn, field: col.field }); } } for (var i = 0, len = sortGrp.length; i < len; i++) { if (typeof sortGrp[parseInt(i.toString(), 10)].direction === 'string') { query.sortBy(sortGrp[parseInt(i.toString(), 10)].field, sortGrp[parseInt(i.toString(), 10)].direction); } else { var col = this.getColumnByField(sortGrp[parseInt(i.toString(), 10)].field); query.sortByForeignKey(sortGrp[parseInt(i.toString(), 10)].field, sortGrp[parseInt(i.toString(), 10)].direction, undefined, col.getSortDirection().toLowerCase()); } } } return query; }; /** * @param {Query} query - specifies the query * @param {Column} fcolumn - specifies the forein key column model * @param {boolean} isForeignKey - Confirms whether the column is a foreign key or not * @returns {Query} - returns the query * @hidden */ Data.prototype.searchQuery = function (query, fcolumn, isForeignKey) { var sSettings = this.parent.searchSettings; var fields = (!isNullOrUndefined(sSettings.fields) && sSettings.fields.length) ? sSettings.fields : this.getSearchColumnFieldNames(); var predicateList = []; var needForeignKeySearch = false; if (!isNullOrUndefined(this.parent.searchSettings.key) && this.parent.searchSettings.key.length) { needForeignKeySearch = this.parent.getForeignKeyColumns().some(function (col) { return fields.indexOf(col.field) > -1; }); var adaptor = !isForeignKey ? this.dataManager.adaptor : fcolumn.dataSource.adaptor; if (needForeignKeySearch || (adaptor.getModuleName && adaptor.getModuleName() === 'ODataV4Adaptor')) { fields = isForeignKey ? [fcolumn.foreignKeyValue] : fields; for (var i = 0; i < fields.length; i++) { var column = isForeignKey ? fcolumn : this.getColumnByField(fields[parseInt(i.toString(), 10)]); if (column.isForeignColumn() && !isForeignKey) { predicateList = this.fGeneratePredicate(column, predicateList); } else { predicateList.push(new Predicate(fields[parseInt(i.toString(), 10)], sSettings.operator, sSettings.key, sSettings.ignoreCase, sSettings.ignoreAccent)); } } var predList = Predicate.or(predicateList); predList.key = sSettings.key; query.where(predList); } else { query.search(sSettings.key, fields, sSettings.operator, sSettings.ignoreCase, sSettings.ignoreAccent); } } return query; }; Data.prototype.filterQuery = function (query, column, skipFoerign) { var gObj = this.parent; var predicateList = []; var actualFilter = []; var foreignColumn = this.parent.getForeignKeyColumns(); var foreignColEmpty; if (gObj.allowFiltering && gObj.filterSettings.columns.length) { var columns = column ? column : gObj.filterSettings.columns; var colType = {}; for (var _i = 0, _a = gObj.getColumns(); _i < _a.length; _i++) { var col = _a[_i]; colType[col.field] = col.filter.type ? col.filter.type : gObj.filterSettings.type; } var foreignCols = []; var defaultFltrCols = []; for (var _b = 0, columns_1 = columns; _b < columns_1.length; _b++) { var col = columns_1[_b]; var gridColumn = col.isForeignKey ? gObj.getColumnByUid(col.uid) : gObj.getColumnByField(col.field); if (isNullOrUndefined(col.type) && gridColumn && (gridColumn.type === 'date' || gridColumn.type === 'datetime' || gridColumn.type === 'dateonly')) { col.type = col.isForeignKey ? gObj.getColumnByUid(col.uid).type : gObj.getColumnByField(col.field).type; } if (col.isForeignKey) { foreignCols.push(col); } else { defaultFltrCols.push(col); } } if (defaultFltrCols.length) { for (var i = 0, len = defaultFltrCols.length; i < len; i++) { defaultFltrCols[parseInt(i.toString(), 10)].uid = defaultFltrCols[parseInt(i.toString(), 10)].uid || this.parent.grabColumnByFieldFromAllCols(defaultFltrCols[parseInt(i.toString(), 10)] .field, defaultFltrCols[parseInt(i.toString(), 10)].isForeignKey).uid; } var excelPredicate = CheckBoxFilterBase.getPredicate(defaultFltrCols); for (var _c = 0, _d = Object.keys(excelPredicate); _c < _d.length; _c++) { var prop = _d[_c]; predicateList.push(excelPredicate["" + prop]); } } if (foreignCols.length) { for (var _e = 0, foreignCols_1 = foreignCols; _e < foreignCols_1.length; _e++) { var col = foreignCols_1[_e]; col.uid = col.uid || this.parent.grabColumnByFieldFromAllCols(col.field, col.isForeignKey).uid; var column_1 = this.parent.grabColumnByUidFromAllCols(col.uid); if (!column_1) { this.parent.log('initial_action', { moduleName: 'filter', columnName: col.field }); } if (column_1.isForeignColumn() && getColumnByForeignKeyValue(col.field, foreignColumn) && !skipFoerign) { actualFilter.push(col); if (!column_1.columnData.length) { foreignColEmpty = true; } predicateList = this.fGeneratePredicate(column_1, predicateList); } else { var excelPredicate = CheckBoxFilterBase.getPredicate(columns); for (var _f = 0, _g = Object.keys(excelPredicate); _f < _g.length; _f++) { var prop = _g[_f]; predicateList.push(excelPredicate["" + prop]); } } } } if (predicateList.length && !foreignColEmpty) { query.where(Predicate.and(predicateList)); } else { this.parent.notify(events.showEmptyGrid, {}); } } return query; }; Data.prototype.fGeneratePredicate = function (col, predicateList) { var fPredicate = {}; if (col) { this.parent.notify(events.generateQuery, { predicate: fPredicate, column: col }); if (fPredicate.predicate.predicates.length) { predicateList.push(fPredicate.predicate); } } return predicateList; }; /** * The function is used to get dataManager promise by executing given Query. * * @param {object} args - specifies the object * @param {string} args.requestType - Defines the request type * @param {string[]} args.foreignKeyData - Defines the foreignKeyData.string * @param {Object} args.data - Defines the data. * @param {number} args.index - Defines the index . * @param {Query} query - Defines the query which will execute along with data processing. * @returns {Promise<Object>} - returns the object * @hidden */ Data.prototype.getData = function (args, query) { var _this = this; if (args === void 0) { args = { requestType: '' }; } var key = this.getKey(args.foreignKeyData && Object.keys(args.foreignKeyData).length ? args.foreignKeyData : this.parent.getPrimaryKeyFieldNames()); this.parent.log('datasource_syntax_mismatch', { dataState: this.parent }); if (this.parent.dataSource && 'result' in this.parent.dataSource) { var def = this.eventPromise(args, query, key); return def.promise; } else { var crud = void 0; switch (args.requestType) { case 'delete': query = query ? query : this.generateQuery(); // eslint-disable-next-line no-case-declarations var len = Object.keys(args.data).length; if (len === 1) { crud = this.dataManager.remove(key, args.data[0], query.fromTable, query); } else { var changes = { addedRecords: [], deletedRecords: [], changedRecords: [] }; changes.deletedRecords = args.data; crud = this.dataManager.saveChanges(changes, key, query.fromTable, query.requiresCount()); } break; case 'save': query = query ? query : this.generateQuery(); args.index = isNullOrUndefined(args.index) ? 0 : args.index; crud = this.dataManager.insert(args.data, query.fromTable, query, args.index); break; } var promise = 'promise'; args["" + promise] = crud; // eslint-disable-next-line no-prototype-builtins if (crud && !Array.isArray(crud) && !crud.hasOwnProperty('deletedRecords')) { return crud.then(function () { return _this.insert(query, args); }); } else { return this.insert(query, args); } } }; Data.prototype.insert = function (query, args) { if (args.requestType === 'save') { args.query = query; this.parent.notify(events.recordAdded, args); } return this.executeQuery(query); }; Data.prototype.executeQuery = function (query) { var _this = this; if (this.dataManager.ready) { var deferred_1 = new Deferred(); var ready = this.dataManager.ready; ready.then(function () { _this.dataManager.executeQuery(query).then(function (result) { deferred_1.resolve(result); }); }).catch(function (e) { deferred_1.reject(e); }); return deferred_1.promise; } else { return this.dataManager.executeQuery(query); } }; Data.prototype.formatGroupColumn = function (value, field) { var serviceLocator = this.serviceLocator; var column = this.getColumnByField(field); var date = value; if (!column.type) { column.type = date.getDay ? (date.getHours() > 0 || date.getMinutes() > 0 || date.getSeconds() > 0 || date.getMilliseconds() > 0 ? 'datetime' : 'date') : typeof (value); } if (isNullOrUndefined(column.getFormatter())) { setFormatter(serviceLocator, column); } var formatVal = ValueFormatter.prototype.toView(value, column.getFormatter()); return formatVal; }; Data.prototype.crudActions = function (args) { var query = this.generateQuery(); var promise = null; var pr = 'promise'; var key = this.getKey(args.foreignKeyData && Object.keys(args.foreignKeyData).length ? args.foreignKeyData : this.parent.getPrimaryKeyFieldNames()); if (this.parent.dataSource && 'result' in this.parent.dataSource) { this.eventPromise(args, query, key); } switch (args.requestType) { case 'save': promise = this.dataManager.update(key, args.data, query.fromTable, query, args.previousData); break; } args["" + pr] = promise ? promise : args["" + pr]; this.parent.notify(events.crudAction, args); }; /** * @param {object} changes - specifies the changes * @param {string} key - specifies the key * @param {object} original - specifies the original data * @param {Query} query - specifies the query * @returns {Promise<Object>} returns the object * @hidden */ Data.prototype.saveChanges = function (changes, key, original, query) { if (query === void 0) { query = this.generateQuery(); } query.requiresCount(); if ('result' in this.parent.dataSource) { var deff = new Deferred(); var args = { requestType: 'batchsave', changes: changes, key: key, query: query, endEdit: deff.resolve }; this.setState({ isPending: true, resolver: deff.resolve }); this.parent.trigger(events.dataSourceChanged, args); return deff.promise; } else { var promise = this.dataManager.saveChanges(changes, key, query.fromTable, query, original); return promise; } }; Data.prototype.getKey = function (keys) { if (keys && keys.length) { return keys[0]; } return undefined; }; /** * @returns {boolean} returns whether its remote data * @hidden */ Data.prototype.isRemote = function () { return this.dataManager.dataSource.offline !== true && this.dataManager.dataSource.url !== undefined && this.dataManager.dataSource.url !== ''; }; /** * clears the cache * @returns {void} * @hidden */ Data.prototype.clearCache = function () { if (this.isRemote()) { this.parent.dataSource.clearCache(); } }; Data.prototype.addRows = function (e) { for (var i = e.records.length; i > 0; i--) { if (this.parent.dataSource instanceof DataManager && this.dataManager.dataSource.offline) { this.dataManager.dataSource.json.splice(e.toIndex, 0, e.records[i - 1]); } else if (((!this.parent.getDataModule().isRemote()) && (!isNullOrUndefined(this.parent.dataSource))) && (!this.parent.dataSource.result)) { this.parent.dataSource['splice'](e.toIndex, 0, e.records[i - 1]); } } }; Data.prototype.removeRows = function (e) { var json = this.dataManager.dataSource.json; if (this.parent.dataSource instanceof DataManager && this.dataManager.dataSource.offline) { this.dataManager.dataSource.json = json.filter(function (value) { return e.records.indexOf(value) === -1; }); } else if (((!this.parent.getDataModule().isRemote()) && (!isNullOrUndefined(this.parent.dataSource))) && (!this.parent.dataSource.result)) { this.parent.dataSource = json.filter(function (value) { return e.records.indexOf(value) === -1; }); } }; Data.prototype.getColumnByField = function (field) { var col; return (this.parent.columnModel).some(function (column) { col = column; return column.field === field; }) && col; }; Data.prototype.destroy = function () { if (this.parent.isDestroyed) { return; } this.parent.off(events.rowsAdded, this.addRows); this.parent.off(events.rowsRemoved, this.removeRows); this.parent.off(events.dataSourceModified, this.initDataManager); this.parent.off(events.destroy, this.destroy); this.parent.off(events.updateData, this.crudActions); this.parent.off(events.addDeleteAction, this.getData); this.parent.off(events.autoCol, this.refreshFilteredCols); this.parent.off(events.columnsPrepared, this.refreshFilteredCols); }; Data.prototype.getState = function () { return this.dataState; }; Data.prototype.setState = function (state) { return this.dataState = state; }; Data.prototype.getForeignKeyDataState = function () { return this.foreignKeyDataState; }; Data.prototype.setForeignKeyDataState = function (state) { this.foreignKeyDataState = state; }; Data.prototype.getStateEventArgument = function (query) { var adaptr = new UrlAdaptor(); var dm = new DataManager({ url: '', adaptor: new UrlAdaptor }); var state = adaptr.processQuery(dm, query); var data = JSON.parse(state.data); return extend(data, state.pvtData); }; Data.prototype.eventPromise = function (args, query, key) { var _this = this; var dataArgs = args; var state = this.getStateEventArgument(query); var def = new Deferred(); var deff = new Deferred(); if ((args.requestType !== undefined || (this.parent.groupSettings.disablePageWiseAggregates && query.queries.some(function (query) { return query.fn === 'onGroup'; }))) && this.dataState.isDataChanged !== false) { state.action = args; if (args.requestType === 'save' || args.requestType === 'delete' || args.requestType === 'batchsave') { var editArgs_1 = args; editArgs_1.key = key; var promise = 'promise'; editArgs_1["" + promise] = deff.promise; editArgs_1.state = state; this.setState({ isPending: true, resolver: deff.resolve }); dataArgs.endEdit = deff.resolve; dataArgs.cancelEdit = deff.reject; this.parent.trigger(events.dataSourceChanged, editArgs_1); deff.promise.then(function () { _this.setState({ isPending: true, resolver: def.resolve, group: state.group, aggregates: state.aggregates }); if (editArgs_1.requestType === 'save') { _this.parent.notify(events.recordAdded, editArgs_1); } _this.parent.trigger(events.dataStateChange, state); }) .catch(function () { return void 0; }); } else { this.setState({ isPending: true, resolver: def.resolve, group: state.group, aggregates: state.aggregates }); this.parent.trigger(events.dataStateChange, state); } } else { this.setState({}); def.resolve(this.parent.dataSource); } return def; }; /** * Gets the columns where searching needs to be performed from the Grid. * * @returns {string[]} returns the searched column field names */ Data.prototype.getSearchColumnFieldNames = function () { var colFieldNames = []; var columns = this.parent.getColumns(); for (var _i = 0, columns_2 = columns; _i < columns_2.length; _i++) { var col = columns_2[_i]; if (col.allowSearching && !isNullOrUndefined(col.field)) { colFieldNames.push(col.field); } } return colFieldNames; }; Data.prototype.refreshFilteredCols = function () { if (this.parent.allowFiltering && this.parent.filterSettings.columns.length) { refreshFilteredColsUid(this.parent, this.parent.filterSettings.columns); } }; return Data; }()); export { Data };