UNPKG

ag-grid

Version:

Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components

534 lines (533 loc) 23.3 kB
/** * ag-grid - Advanced Data Grid / Data Table supporting Javascript / React / AngularJS / Web Components * @version v18.1.2 * @link http://www.ag-grid.com/ * @license MIT */ "use strict"; var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; return c > 3 && r && Object.defineProperty(target, key, r), r; }; var __metadata = (this && this.__metadata) || function (k, v) { if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); }; Object.defineProperty(exports, "__esModule", { value: true }); var utils_1 = require("../utils"); var gridOptionsWrapper_1 = require("../gridOptionsWrapper"); var popupService_1 = require("../widgets/popupService"); var valueService_1 = require("../valueService/valueService"); var columnController_1 = require("../columnController/columnController"); var columnApi_1 = require("../columnController/columnApi"); var context_1 = require("../context/context"); var eventService_1 = require("../eventService"); var events_1 = require("../events"); var gridApi_1 = require("../gridApi"); var componentResolver_1 = require("../components/framework/componentResolver"); var FilterManager = (function () { function FilterManager() { this.allFilters = {}; this.quickFilter = null; this.quickFilterParts = null; } FilterManager_1 = FilterManager; FilterManager.prototype.init = function () { this.eventService.addEventListener(events_1.Events.EVENT_ROW_DATA_CHANGED, this.onNewRowsLoaded.bind(this)); this.eventService.addEventListener(events_1.Events.EVENT_NEW_COLUMNS_LOADED, this.onNewColumnsLoaded.bind(this)); this.quickFilter = this.parseQuickFilter(this.gridOptionsWrapper.getQuickFilterText()); this.setQuickFilterParts(); // check this here, in case there is a filter from the start this.checkExternalFilter(); }; FilterManager.prototype.setQuickFilterParts = function () { if (this.quickFilter) { this.quickFilterParts = this.quickFilter.split(' '); } else { this.quickFilterParts = null; } }; FilterManager.prototype.setFilterModel = function (model) { var _this = this; var allPromises = []; if (model) { // mark the filters as we set them, so any active filters left over we stop var modelKeys_1 = Object.keys(model); utils_1.Utils.iterateObject(this.allFilters, function (colId, filterWrapper) { utils_1.Utils.removeFromArray(modelKeys_1, colId); var newModel = model[colId]; _this.setModelOnFilterWrapper(filterWrapper.filterPromise, newModel); allPromises.push(filterWrapper.filterPromise); }); // at this point, processedFields contains data for which we don't have a filter working yet utils_1.Utils.iterateArray(modelKeys_1, function (colId) { var column = _this.columnController.getPrimaryColumn(colId); if (!column) { console.warn('Warning ag-grid setFilterModel - no column found for colId ' + colId); return; } var filterWrapper = _this.getOrCreateFilterWrapper(column); _this.setModelOnFilterWrapper(filterWrapper.filterPromise, model[colId]); allPromises.push(filterWrapper.filterPromise); }); } else { utils_1.Utils.iterateObject(this.allFilters, function (key, filterWrapper) { _this.setModelOnFilterWrapper(filterWrapper.filterPromise, null); allPromises.push(filterWrapper.filterPromise); }); } utils_1.Promise.all(allPromises).then(function (whatever) { _this.onFilterChanged(); }); }; FilterManager.prototype.setModelOnFilterWrapper = function (filterPromise, newModel) { filterPromise.then(function (filter) { if (typeof filter.setModel !== 'function') { console.warn('Warning ag-grid - filter missing setModel method, which is needed for setFilterModel'); return; } filter.setModel(newModel); }); }; FilterManager.prototype.getFilterModel = function () { var result = {}; utils_1.Utils.iterateObject(this.allFilters, function (key, filterWrapper) { // because user can provide filters, we provide useful error checking and messages var filterPromise = filterWrapper.filterPromise; var filter = filterPromise.resolveNow(null, function (filter) { return filter; }); if (filter == null) { return null; } if (typeof filter.getModel !== 'function') { console.warn('Warning ag-grid - filter API missing getModel method, which is needed for getFilterModel'); return; } var model = filter.getModel(); if (utils_1.Utils.exists(model)) { result[key] = model; } }); return result; }; // returns true if any advanced filter (ie not quick filter) active FilterManager.prototype.isAdvancedFilterPresent = function () { return this.advancedFilterPresent; }; FilterManager.prototype.setAdvancedFilterPresent = function () { var atLeastOneActive = false; utils_1.Utils.iterateObject(this.allFilters, function (key, filterWrapper) { if (filterWrapper.filterPromise.resolveNow(false, function (filter) { return filter.isFilterActive(); })) { atLeastOneActive = true; } }); this.advancedFilterPresent = atLeastOneActive; }; FilterManager.prototype.updateFilterFlagInColumns = function (source) { utils_1.Utils.iterateObject(this.allFilters, function (key, filterWrapper) { var filterActive = filterWrapper.filterPromise.resolveNow(false, function (filter) { return filter.isFilterActive(); }); filterWrapper.column.setFilterActive(filterActive, source); }); }; // returns true if quickFilter or advancedFilter FilterManager.prototype.isAnyFilterPresent = function () { return this.isQuickFilterPresent() || this.advancedFilterPresent || this.externalFilterPresent; }; FilterManager.prototype.doesFilterPass = function (node, filterToSkip) { var data = node.data; var colKeys = Object.keys(this.allFilters); for (var i = 0, l = colKeys.length; i < l; i++) { var colId = colKeys[i]; var filterWrapper = this.allFilters[colId]; // if no filter, always pass if (filterWrapper === undefined) { continue; } var filter = filterWrapper.filterPromise.resolveNow(undefined, function (filter) { return filter; }); // if filter not yet there, continue if (filter === undefined) { continue; } if (filter === filterToSkip) { continue; } // don't bother with filters that are not active if (!filter.isFilterActive()) { continue; } if (!filter.doesFilterPass) { console.error('Filter is missing method doesFilterPass'); } var params = { node: node, data: data }; if (!filter.doesFilterPass(params)) { return false; } } // all filters passed return true; }; FilterManager.prototype.parseQuickFilter = function (newFilter) { if (utils_1.Utils.missing(newFilter) || newFilter === "") { return null; } if (this.gridOptionsWrapper.isRowModelInfinite()) { console.warn('ag-grid: cannot do quick filtering when doing virtual paging'); return null; } return newFilter.toUpperCase(); }; // returns true if it has changed (not just same value again) FilterManager.prototype.setQuickFilter = function (newFilter) { var parsedFilter = this.parseQuickFilter(newFilter); if (this.quickFilter !== parsedFilter) { this.quickFilter = parsedFilter; this.setQuickFilterParts(); this.onFilterChanged(); } }; FilterManager.prototype.checkExternalFilter = function () { this.externalFilterPresent = this.gridOptionsWrapper.isExternalFilterPresent(); }; FilterManager.prototype.onFilterChanged = function () { this.setAdvancedFilterPresent(); this.updateFilterFlagInColumns("filterChanged"); this.checkExternalFilter(); utils_1.Utils.iterateObject(this.allFilters, function (key, filterWrapper) { filterWrapper.filterPromise.then(function (filter) { if (filter.onAnyFilterChanged) { filter.onAnyFilterChanged(); } }); }); var event = { type: events_1.Events.EVENT_FILTER_CHANGED, api: this.gridApi, columnApi: this.columnApi }; this.eventService.dispatchEvent(event); }; FilterManager.prototype.isQuickFilterPresent = function () { return this.quickFilter !== null; }; FilterManager.prototype.doesRowPassOtherFilters = function (filterToSkip, node) { return this.doesRowPassFilter(node, filterToSkip); }; FilterManager.prototype.doesRowPassQuickFilterNoCache = function (node, filterPart) { var _this = this; var columns = this.columnController.getAllColumnsForQuickFilter(); var filterPasses = false; columns.forEach(function (column) { if (filterPasses) { return; } var part = _this.getQuickFilterTextForColumn(column, node); if (utils_1.Utils.exists(part)) { if (part.indexOf(filterPart) >= 0) { filterPasses = true; } } }); return filterPasses; }; FilterManager.prototype.doesRowPassQuickFilterCache = function (node, filterPart) { if (!node.quickFilterAggregateText) { this.aggregateRowForQuickFilter(node); } var filterPasses = node.quickFilterAggregateText.indexOf(filterPart) >= 0; return filterPasses; }; FilterManager.prototype.doesRowPassQuickFilter = function (node) { var _this = this; var filterPasses = true; var usingCache = this.gridOptionsWrapper.isCacheQuickFilter(); this.quickFilterParts.forEach(function (filterPart) { var partPasses = usingCache ? _this.doesRowPassQuickFilterCache(node, filterPart) : _this.doesRowPassQuickFilterNoCache(node, filterPart); // each part must pass, if any fails, then the whole filter fails if (!partPasses) { filterPasses = false; } }); return filterPasses; }; FilterManager.prototype.doesRowPassFilter = function (node, filterToSkip) { // the row must pass ALL of the filters, so if any of them fail, // we return true. that means if a row passes the quick filter, // but fails the column filter, it fails overall // first up, check quick filter if (this.isQuickFilterPresent()) { if (!this.doesRowPassQuickFilter(node)) { return false; } } // secondly, give the client a chance to reject this row if (this.externalFilterPresent) { if (!this.gridOptionsWrapper.doesExternalFilterPass(node)) { return false; } } // lastly, check our internal advanced filter if (this.advancedFilterPresent) { if (!this.doesFilterPass(node, filterToSkip)) { return false; } } // got this far, all filters pass return true; }; FilterManager.prototype.getQuickFilterTextForColumn = function (column, rowNode) { var value = this.valueService.getValue(column, rowNode, true); var valueAfterCallback; var colDef = column.getColDef(); if (column.getColDef().getQuickFilterText) { var params = { value: value, node: rowNode, data: rowNode.data, column: column, colDef: colDef }; valueAfterCallback = column.getColDef().getQuickFilterText(params); } else { valueAfterCallback = value; } if (valueAfterCallback && valueAfterCallback !== '') { return valueAfterCallback.toString().toUpperCase(); } else { return null; } }; FilterManager.prototype.aggregateRowForQuickFilter = function (node) { var _this = this; var stringParts = []; var columns = this.columnController.getAllColumnsForQuickFilter(); columns.forEach(function (column) { var part = _this.getQuickFilterTextForColumn(column, node); if (utils_1.Utils.exists(part)) { stringParts.push(part); } }); node.quickFilterAggregateText = stringParts.join(FilterManager_1.QUICK_FILTER_SEPARATOR); }; FilterManager.prototype.onNewRowsLoaded = function (source) { utils_1.Utils.iterateObject(this.allFilters, function (key, filterWrapper) { filterWrapper.filterPromise.then(function (filter) { if (filter.onNewRowsLoaded) { filter.onNewRowsLoaded(); } }); }); this.updateFilterFlagInColumns(source); this.setAdvancedFilterPresent(); }; FilterManager.prototype.createValueGetter = function (column) { var _this = this; return function (node) { return _this.valueService.getValue(column, node, true); }; }; FilterManager.prototype.getFilterComponent = function (column) { var filterWrapper = this.getOrCreateFilterWrapper(column); return filterWrapper.filterPromise; }; FilterManager.prototype.getOrCreateFilterWrapper = function (column) { var filterWrapper = this.cachedFilter(column); if (!filterWrapper) { filterWrapper = this.createFilterWrapper(column); this.allFilters[column.getColId()] = filterWrapper; } return filterWrapper; }; FilterManager.prototype.cachedFilter = function (column) { return this.allFilters[column.getColId()]; }; FilterManager.prototype.createFilterInstance = function (column, $scope) { var _this = this; var defaultFilter = 'agTextColumnFilter'; if (this.gridOptionsWrapper.isEnterprise()) { defaultFilter = 'agSetColumnFilter'; } var sanitisedColDef = utils_1.Utils.cloneObject(column.getColDef()); var event = { type: events_1.Events.EVENT_FILTER_MODIFIED, api: this.gridApi, columnApi: this.columnApi }; var filterChangedCallback = this.onFilterChanged.bind(this); var filterModifiedCallback = function () { return _this.eventService.dispatchEvent(event); }; var params = { column: column, colDef: sanitisedColDef, rowModel: this.rowModel, filterChangedCallback: filterChangedCallback, filterModifiedCallback: filterModifiedCallback, valueGetter: this.createValueGetter(column), context: this.gridOptionsWrapper.getContext(), doesRowPassOtherFilter: null, $scope: $scope }; return this.componentResolver.createAgGridComponent(sanitisedColDef, params, 'filter', { api: this.gridApi, columnApi: this.columnApi, column: column, colDef: sanitisedColDef }, defaultFilter, true, function (params, filter) { return utils_1.Utils.assign(params, { doesRowPassOtherFilter: _this.doesRowPassOtherFilters.bind(_this, filter), }); }); }; FilterManager.prototype.createFilterWrapper = function (column) { var filterWrapper = { column: column, filterPromise: null, scope: null, compiledElement: null, guiPromise: utils_1.Promise.external() }; filterWrapper.scope = this.gridOptionsWrapper.isAngularCompileFilters() ? this.$scope.$new() : null; filterWrapper.filterPromise = this.createFilterInstance(column, filterWrapper.scope); this.putIntoGui(filterWrapper); return filterWrapper; }; FilterManager.prototype.putIntoGui = function (filterWrapper) { var _this = this; var eFilterGui = document.createElement('div'); eFilterGui.className = 'ag-filter'; filterWrapper.filterPromise.then(function (filter) { var guiFromFilter = filter.getGui(); if (utils_1.Utils.missing(guiFromFilter)) { console.warn("getGui method from filter returned " + guiFromFilter + ", it should be a DOM element or an HTML template string."); } // for backwards compatibility with Angular 1 - we // used to allow providing back HTML from getGui(). // once we move away from supporting Angular 1 // directly, we can change this. if (typeof guiFromFilter === 'string') { guiFromFilter = utils_1.Utils.loadTemplate(guiFromFilter); } eFilterGui.appendChild(guiFromFilter); if (filterWrapper.scope) { var compiledElement = _this.$compile(eFilterGui)(filterWrapper.scope); filterWrapper.compiledElement = compiledElement; setTimeout(function () { return filterWrapper.scope.$apply(); }, 0); } filterWrapper.guiPromise.resolve(eFilterGui); }); }; FilterManager.prototype.onNewColumnsLoaded = function () { this.destroy(); }; // destroys the filter, so it not longer takes part FilterManager.prototype.destroyFilter = function (column, source) { if (source === void 0) { source = "api"; } var filterWrapper = this.allFilters[column.getColId()]; if (filterWrapper) { this.disposeFilterWrapper(filterWrapper, source); this.onFilterChanged(); } }; FilterManager.prototype.disposeFilterWrapper = function (filterWrapper, source) { var _this = this; filterWrapper.filterPromise.then(function (filter) { filter.setModel(null); if (filter.destroy) { filter.destroy(); } filterWrapper.column.setFilterActive(false, source); if (filterWrapper.scope) { if (filterWrapper.compiledElement) { filterWrapper.compiledElement.remove(); } filterWrapper.scope.$destroy(); } delete _this.allFilters[filterWrapper.column.getColId()]; }); }; FilterManager.prototype.destroy = function () { var _this = this; utils_1.Utils.iterateObject(this.allFilters, function (key, filterWrapper) { _this.disposeFilterWrapper(filterWrapper, "filterDestroyed"); }); }; FilterManager.QUICK_FILTER_SEPARATOR = '\n'; __decorate([ context_1.Autowired('$compile'), __metadata("design:type", Object) ], FilterManager.prototype, "$compile", void 0); __decorate([ context_1.Autowired('$scope'), __metadata("design:type", Object) ], FilterManager.prototype, "$scope", void 0); __decorate([ context_1.Autowired('gridOptionsWrapper'), __metadata("design:type", gridOptionsWrapper_1.GridOptionsWrapper) ], FilterManager.prototype, "gridOptionsWrapper", void 0); __decorate([ context_1.Autowired('gridCore'), __metadata("design:type", Object) ], FilterManager.prototype, "gridCore", void 0); __decorate([ context_1.Autowired('popupService'), __metadata("design:type", popupService_1.PopupService) ], FilterManager.prototype, "popupService", void 0); __decorate([ context_1.Autowired('valueService'), __metadata("design:type", valueService_1.ValueService) ], FilterManager.prototype, "valueService", void 0); __decorate([ context_1.Autowired('columnController'), __metadata("design:type", columnController_1.ColumnController) ], FilterManager.prototype, "columnController", void 0); __decorate([ context_1.Autowired('rowModel'), __metadata("design:type", Object) ], FilterManager.prototype, "rowModel", void 0); __decorate([ context_1.Autowired('eventService'), __metadata("design:type", eventService_1.EventService) ], FilterManager.prototype, "eventService", void 0); __decorate([ context_1.Autowired('enterprise'), __metadata("design:type", Boolean) ], FilterManager.prototype, "enterprise", void 0); __decorate([ context_1.Autowired('context'), __metadata("design:type", context_1.Context) ], FilterManager.prototype, "context", void 0); __decorate([ context_1.Autowired('columnApi'), __metadata("design:type", columnApi_1.ColumnApi) ], FilterManager.prototype, "columnApi", void 0); __decorate([ context_1.Autowired('gridApi'), __metadata("design:type", gridApi_1.GridApi) ], FilterManager.prototype, "gridApi", void 0); __decorate([ context_1.Autowired('componentResolver'), __metadata("design:type", componentResolver_1.ComponentResolver) ], FilterManager.prototype, "componentResolver", void 0); __decorate([ context_1.PostConstruct, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], FilterManager.prototype, "init", null); __decorate([ context_1.PreDestroy, __metadata("design:type", Function), __metadata("design:paramtypes", []), __metadata("design:returntype", void 0) ], FilterManager.prototype, "destroy", null); FilterManager = FilterManager_1 = __decorate([ context_1.Bean('filterManager') ], FilterManager); return FilterManager; var FilterManager_1; }()); exports.FilterManager = FilterManager;