From 388bd115c1a15f853da8ac943a6e5e3574630438 Mon Sep 17 00:00:00 2001 From: Ghislain B Date: Wed, 6 Dec 2023 10:49:06 -0500 Subject: [PATCH] feat: use PubSub Service singleton to subscribe to any SlickEvent (#1248) * feat: use PubSub Service singleton to subscribe to any SlickEvent - by modifying the SlickEvent class to also publish an event when a PubSub Service is provided to a SlickEvent, we can avoid having our previous monkey patch of subscribing to **all** SlickGrid/DataView events to then dispatch event, this acted like a middleware, we can avoid all of that middleware with this new approach and publish right away via the PubSub when provided - also removed `defaultComponentEventPrefix`, `defaultSlickgridEventPrefix` grid options since they will not be used anymore --- .../src/core/__tests__/slickCore.spec.ts | 47 +++++ .../src/core/__tests__/slickGrid.spec.ts | 4 +- packages/common/src/core/slickCore.ts | 70 ++++++-- packages/common/src/core/slickDataview.ts | 33 ++-- packages/common/src/core/slickGrid.ts | 165 ++++++++++++------ packages/common/src/global-grid-options.ts | 2 - .../src/interfaces/gridOption.interface.ts | 6 - .../event-pub-sub/src/eventPubSub.service.ts | 1 + .../__tests__/slick-vanilla-grid.spec.ts | 18 +- .../components/slick-vanilla-grid-bundle.ts | 24 +-- 10 files changed, 238 insertions(+), 132 deletions(-) diff --git a/packages/common/src/core/__tests__/slickCore.spec.ts b/packages/common/src/core/__tests__/slickCore.spec.ts index b65e04e14..179c17269 100644 --- a/packages/common/src/core/__tests__/slickCore.spec.ts +++ b/packages/common/src/core/__tests__/slickCore.spec.ts @@ -1,7 +1,16 @@ import 'jest-extended'; +import { BasePubSubService } from '@slickgrid-universal/event-pub-sub'; + import { EditController } from '../../interfaces'; import { SlickEditorLock, SlickEvent, SlickEventData, SlickEventHandler, SlickGroup, SlickGroupTotals, SlickRange, Utils } from '../slickCore'; +const pubSubServiceStub = { + publish: jest.fn(), + subscribe: jest.fn(), + unsubscribe: jest.fn(), + unsubscribeAll: jest.fn(), +} as BasePubSubService; + describe('SlickCore file', () => { describe('SlickEventData class', () => { it('should call isPropagationStopped() and expect truthy when event propagation is stopped by calling stopPropagation()', () => { @@ -97,6 +106,44 @@ describe('SlickCore file', () => { expect(spy1).toHaveBeenCalledWith(ed, { hello: 'world' }); }); + + it('should be able to add a PubSub instance to the SlickEvent call notify() and expect PubSub .publish() to be called as well', () => { + const ed = new SlickEventData(); + const onClick = new SlickEvent('onClick', pubSubServiceStub); + + onClick.notify({ hello: 'world' }, ed); + + expect(pubSubServiceStub.publish).toHaveBeenCalledWith('onClick', { eventData: ed, args: { hello: 'world' } }); + }); + + it('should be able to mix a PubSub with regular SlickEvent subscribe and expect both to be triggered by the SlickEvent call notify()', () => { + const spy1 = jest.fn(); + const spy2 = jest.fn(); + const ed = new SlickEventData(); + const onClick = new SlickEvent('onClick', pubSubServiceStub); + onClick.subscribe(spy1); + onClick.subscribe(spy2); + + expect(onClick.subscriberCount).toBe(2); + + onClick.notify({ hello: 'world' }, ed); + + expect(spy1).toHaveBeenCalledWith(ed, { hello: 'world' }); + expect(pubSubServiceStub.publish).toHaveBeenCalledWith('onClick', { eventData: ed, args: { hello: 'world' } }); + }); + + it('should be able to call addSlickEventPubSubWhenDefined() and expect PubSub to be available in SlickEvent', () => { + const ed = new SlickEventData(); + const onClick = new SlickEvent('onClick'); + const scope = { onClick }; + const setPubSubSpy = jest.spyOn(onClick, 'setPubSubService'); + + Utils.addSlickEventPubSubWhenDefined(pubSubServiceStub, scope); + onClick.notify({ hello: 'world' }, ed); + + expect(setPubSubSpy).toHaveBeenCalledWith(pubSubServiceStub); + expect(pubSubServiceStub.publish).toHaveBeenCalledWith('onClick', { eventData: ed, args: { hello: 'world' } }); + }); }); describe('SlickEventHandler class', () => { diff --git a/packages/common/src/core/__tests__/slickGrid.spec.ts b/packages/common/src/core/__tests__/slickGrid.spec.ts index 69490b0ad..6c58a9c50 100644 --- a/packages/common/src/core/__tests__/slickGrid.spec.ts +++ b/packages/common/src/core/__tests__/slickGrid.spec.ts @@ -20,7 +20,7 @@ describe('SlickGrid core file', () => { it('should be able to instantiate SlickGrid without DataView', () => { const columns = [{ id: 'firstName', field: 'firstName', name: 'First Name' }] as Column[]; const options = { enableCellNavigation: true } as GridOption; - grid = new SlickGrid('#myGrid', [], columns, options, true); + grid = new SlickGrid('#myGrid', [], columns, options, undefined, true); grid.init(); expect(grid).toBeTruthy(); @@ -31,7 +31,7 @@ describe('SlickGrid core file', () => { const columns = [{ id: 'firstName', field: 'firstName', name: 'First Name' }] as Column[]; const options = { enableCellNavigation: true } as GridOption; const dv = new SlickDataView({}); - grid = new SlickGrid('#myGrid', dv, columns, options, true); + grid = new SlickGrid('#myGrid', dv, columns, options, undefined, true); grid.init(); expect(grid).toBeTruthy(); diff --git a/packages/common/src/core/slickCore.ts b/packages/common/src/core/slickCore.ts index b20f121e7..d2f5b11e5 100644 --- a/packages/common/src/core/slickCore.ts +++ b/packages/common/src/core/slickCore.ts @@ -14,6 +14,11 @@ import type { CSSStyleDeclarationWritable, EditController } from '../interfaces' export type Handler = (e: any, args: ArgType) => void; +export interface BasePubSub { + publish(_eventName: string | any, _data?: ArgType): any; + subscribe(_eventName: string | Function, _callback: (data: ArgType) => void): any; +} + /** * An event object for passing data to event handlers and letting them control propagation. *

This is pretty much identical to how W3C and jQuery implement events.

@@ -125,10 +130,20 @@ export class SlickEventData { * @constructor */ export class SlickEvent { - protected handlers: Handler[] = []; + protected _handlers: Handler[] = []; + protected _pubSubService?: BasePubSub; get subscriberCount() { - return this.handlers.length; + return this._handlers.length; + } + + /** + * Constructor + * @param {String} [eventName] - event name that could be used for dispatching CustomEvent (when enabled) + * @param {BasePubSub} [pubSubService] - event name that could be used for dispatching CustomEvent (when enabled) + */ + constructor(protected readonly eventName?: string, protected readonly pubSub?: BasePubSub) { + this._pubSubService = pubSub; } /** @@ -136,21 +151,21 @@ export class SlickEvent { *

Event handler will receive two arguments - an EventData and the data * object the event was fired with.

* @method subscribe - * @param fn {Function} Event handler. + * @param {Function} fn - Event handler. */ subscribe(fn: Handler) { - this.handlers.push(fn); + this._handlers.push(fn); } /** * Removes an event handler added with subscribe(fn). * @method unsubscribe - * @param fn {Function} Event handler to be removed. + * @param {Function} [fn] - Event handler to be removed. */ unsubscribe(fn?: Handler) { - for (let i = this.handlers.length - 1; i >= 0; i--) { - if (this.handlers[i] === fn) { - this.handlers.splice(i, 1); + for (let i = this._handlers.length - 1; i >= 0; i--) { + if (this._handlers[i] === fn) { + this._handlers.splice(i, 1); } } } @@ -158,27 +173,32 @@ export class SlickEvent { /** * Fires an event notifying all subscribers. * @method notify - * @param args {Object} Additional data object to be passed to all handlers. - * @param e {EventData} - * Optional. - * An EventData object to be passed to all handlers. + * @param {Object} args Additional data object to be passed to all handlers. + * @param {EventData} [event] - An EventData object to be passed to all handlers. * For DOM events, an existing W3C event object can be passed in. - * @param scope {Object} - * Optional. - * The scope ("this") within which the handler will be executed. + * @param {Object} [scope] - The scope ("this") within which the handler will be executed. * If not specified, the scope will be set to the Event instance. */ notify(args: ArgType, evt?: SlickEventData | Event | MergeTypes | null, scope?: any) { const sed = evt instanceof SlickEventData ? evt : new SlickEventData(evt, args); scope = scope || this; - for (let i = 0; i < this.handlers.length && !(sed.isPropagationStopped() || sed.isImmediatePropagationStopped()); i++) { - const returnValue = this.handlers[i].call(scope, sed as SlickEvent | SlickEventData, args); + for (let i = 0; i < this._handlers.length && !(sed.isPropagationStopped() || sed.isImmediatePropagationStopped()); i++) { + const returnValue = this._handlers[i].call(scope, sed as SlickEvent | SlickEventData, args); sed.addReturnValue(returnValue); } + // user can optionally add a global PubSub Service which makes it easy to publish/subscribe to events + if (typeof this._pubSubService?.publish === 'function' && this.eventName) { + const ret = this._pubSubService.publish<{ args: ArgType; eventData?: Event | SlickEventData; nativeEvent?: Event; }>(this.eventName, { args, eventData: sed }); + sed.addReturnValue(ret); + } return sed; } + + setPubSubService(pubSub: BasePubSub) { + this._pubSubService = pubSub; + } } export class SlickEventHandler { @@ -730,6 +750,22 @@ export class Utils { } } } + + /** + * User could optionally add PubSub Service to SlickEvent + * When it is defined then a SlickEvent `notify()` call will also dispatch it by using the PubSub publish() method + * @param {BasePubSub} [pubSubService] + * @param {*} scope + */ + public static addSlickEventPubSubWhenDefined(pubSub?: BasePubSub, scope?: T) { + if (pubSub) { + for (const prop in scope) { + if (scope[prop] instanceof SlickEvent && typeof (scope[prop] as SlickEvent).setPubSubService === 'function') { + (scope[prop] as SlickEvent).setPubSubService(pubSub); + } + } + } + } } export const SlickGlobalEditorLock = new SlickEditorLock(); diff --git a/packages/common/src/core/slickDataview.ts b/packages/common/src/core/slickDataview.ts index d4e518a92..d4c8b49e8 100644 --- a/packages/common/src/core/slickDataview.ts +++ b/packages/common/src/core/slickDataview.ts @@ -19,6 +19,7 @@ import type { } from '../interfaces'; import { CssStyleHash, CustomDataView } from '../interfaces/gridOption.interface'; import { + type BasePubSub, SlickEvent, SlickEventData, SlickGroup, @@ -114,17 +115,27 @@ export class SlickDataView implements CustomD protected _options: DataViewOption; // public events - onBeforePagingInfoChanged = new SlickEvent(); - onGroupExpanded = new SlickEvent(); - onGroupCollapsed = new SlickEvent(); - onPagingInfoChanged = new SlickEvent(); - onRowCountChanged = new SlickEvent(); - onRowsChanged = new SlickEvent(); - onRowsOrCountChanged = new SlickEvent(); - onSelectedRowIdsChanged = new SlickEvent(); - onSetItemsCalled = new SlickEvent(); - - constructor(options: Partial) { + onBeforePagingInfoChanged: SlickEvent; + onGroupExpanded: SlickEvent; + onGroupCollapsed: SlickEvent; + onPagingInfoChanged: SlickEvent; + onRowCountChanged: SlickEvent; + onRowsChanged: SlickEvent; + onRowsOrCountChanged: SlickEvent; + onSelectedRowIdsChanged: SlickEvent; + onSetItemsCalled: SlickEvent; + + constructor(options: Partial, protected externalPubSub?: BasePubSub) { + this.onBeforePagingInfoChanged = new SlickEvent('onBeforePagingInfoChanged', externalPubSub); + this.onGroupExpanded = new SlickEvent('onGroupExpanded', externalPubSub); + this.onGroupCollapsed = new SlickEvent('onGroupCollapsed', externalPubSub); + this.onPagingInfoChanged = new SlickEvent('onPagingInfoChanged', externalPubSub); + this.onRowCountChanged = new SlickEvent('onRowCountChanged', externalPubSub); + this.onRowsChanged = new SlickEvent('onRowsChanged', externalPubSub); + this.onRowsOrCountChanged = new SlickEvent('onRowsOrCountChanged', externalPubSub); + this.onSelectedRowIdsChanged = new SlickEvent('onSelectedRowIdsChanged', externalPubSub); + this.onSetItemsCalled = new SlickEvent('onSetItemsCalled', externalPubSub); + this._options = Utils.extend(true, {}, this.defaults, options); } diff --git a/packages/common/src/core/slickGrid.ts b/packages/common/src/core/slickGrid.ts index cf4f49fa0..cac2d148a 100644 --- a/packages/common/src/core/slickGrid.ts +++ b/packages/common/src/core/slickGrid.ts @@ -5,6 +5,7 @@ import { BindingEventService } from '@slickgrid-universal/binding'; import { isDefined, isPrimitiveOrHTML } from '@slickgrid-universal/utils'; import { + type BasePubSub, preClickClassName, type SlickEditorLock, SlickGlobalEditorLock, @@ -114,57 +115,57 @@ export class SlickGrid = Column, O e cid = ''; // Events - onActiveCellChanged = new SlickEvent(); - onActiveCellPositionChanged = new SlickEvent(); - onAddNewRow = new SlickEvent(); - onAutosizeColumns = new SlickEvent(); - onBeforeAppendCell = new SlickEvent(); - onBeforeCellEditorDestroy = new SlickEvent(); - onBeforeColumnsResize = new SlickEvent(); - onBeforeDestroy = new SlickEvent(); - onBeforeEditCell = new SlickEvent(); - onBeforeFooterRowCellDestroy = new SlickEvent(); - onBeforeHeaderCellDestroy = new SlickEvent(); - onBeforeHeaderRowCellDestroy = new SlickEvent(); - onBeforeSetColumns = new SlickEvent(); - onBeforeSort = new SlickEvent(); - onBeforeUpdateColumns = new SlickEvent(); - onCellChange = new SlickEvent(); - onCellCssStylesChanged = new SlickEvent(); - onClick = new SlickEvent(); - onColumnsReordered = new SlickEvent(); - onColumnsDrag = new SlickEvent(); - onColumnsResized = new SlickEvent(); - onColumnsResizeDblClick = new SlickEvent(); - onCompositeEditorChange = new SlickEvent(); - onContextMenu = new SlickEvent(); - onDrag = new SlickEvent(); - onDblClick = new SlickEvent(); - onDragInit = new SlickEvent(); - onDragStart = new SlickEvent(); - onDragEnd = new SlickEvent(); - onFooterClick = new SlickEvent(); - onFooterContextMenu = new SlickEvent(); - onFooterRowCellRendered = new SlickEvent(); - onHeaderCellRendered = new SlickEvent(); - onHeaderClick = new SlickEvent(); - onHeaderContextMenu = new SlickEvent(); - onHeaderMouseEnter = new SlickEvent(); - onHeaderMouseLeave = new SlickEvent(); - onHeaderRowCellRendered = new SlickEvent(); - onHeaderRowMouseEnter = new SlickEvent(); - onHeaderRowMouseLeave = new SlickEvent(); - onKeyDown = new SlickEvent(); - onMouseEnter = new SlickEvent(); - onMouseLeave = new SlickEvent(); - onRendered = new SlickEvent(); - onScroll = new SlickEvent(); - onSelectedRowsChanged = new SlickEvent(); - onSetOptions = new SlickEvent(); - onActivateChangedOptions = new SlickEvent(); - onSort = new SlickEvent(); - onValidationError = new SlickEvent(); - onViewportChanged = new SlickEvent(); + onActiveCellChanged: SlickEvent; + onActiveCellPositionChanged: SlickEvent; + onAddNewRow: SlickEvent; + onAutosizeColumns: SlickEvent; + onBeforeAppendCell: SlickEvent; + onBeforeCellEditorDestroy: SlickEvent; + onBeforeColumnsResize: SlickEvent; + onBeforeDestroy: SlickEvent; + onBeforeEditCell: SlickEvent; + onBeforeFooterRowCellDestroy: SlickEvent; + onBeforeHeaderCellDestroy: SlickEvent; + onBeforeHeaderRowCellDestroy: SlickEvent; + onBeforeSetColumns: SlickEvent; + onBeforeSort: SlickEvent; + onBeforeUpdateColumns: SlickEvent; + onCellChange: SlickEvent; + onCellCssStylesChanged: SlickEvent; + onClick: SlickEvent; + onColumnsReordered: SlickEvent; + onColumnsDrag: SlickEvent; + onColumnsResized: SlickEvent; + onColumnsResizeDblClick: SlickEvent; + onCompositeEditorChange: SlickEvent; + onContextMenu: SlickEvent; + onDrag: SlickEvent; + onDblClick: SlickEvent; + onDragInit: SlickEvent; + onDragStart: SlickEvent; + onDragEnd: SlickEvent; + onFooterClick: SlickEvent; + onFooterContextMenu: SlickEvent; + onFooterRowCellRendered: SlickEvent; + onHeaderCellRendered: SlickEvent; + onHeaderClick: SlickEvent; + onHeaderContextMenu: SlickEvent; + onHeaderMouseEnter: SlickEvent; + onHeaderMouseLeave: SlickEvent; + onHeaderRowCellRendered: SlickEvent; + onHeaderRowMouseEnter: SlickEvent; + onHeaderRowMouseLeave: SlickEvent; + onKeyDown: SlickEvent; + onMouseEnter: SlickEvent; + onMouseLeave: SlickEvent; + onRendered: SlickEvent; + onScroll: SlickEvent; + onSelectedRowsChanged: SlickEvent; + onSetOptions: SlickEvent; + onActivateChangedOptions: SlickEvent; + onSort: SlickEvent; + onValidationError: SlickEvent; + onViewportChanged: SlickEvent; // --- // protected variables @@ -453,7 +454,59 @@ export class SlickGrid = Column, O e * @param {Array} columns - An array of column definitions. * @param {Object} [options] - Grid this._options. **/ - constructor(protected container: HTMLElement | string, protected data: CustomDataView | TData[], protected columns: C[], protected options: Partial, protected devMode = false) { + constructor(protected container: HTMLElement | string, protected data: CustomDataView | TData[], protected columns: C[], protected options: Partial, protected externalPubSub?: BasePubSub, protected devMode = false) { + this.onActiveCellChanged = new SlickEvent('onActiveCellChanged', externalPubSub); + this.onActiveCellPositionChanged = new SlickEvent('onActiveCellPositionChanged', externalPubSub); + this.onAddNewRow = new SlickEvent('onAddNewRow', externalPubSub); + this.onAutosizeColumns = new SlickEvent('onAutosizeColumns', externalPubSub); + this.onBeforeAppendCell = new SlickEvent('onBeforeAppendCell', externalPubSub); + this.onBeforeCellEditorDestroy = new SlickEvent('onBeforeCellEditorDestroy', externalPubSub); + this.onBeforeColumnsResize = new SlickEvent('onBeforeColumnsResize', externalPubSub); + this.onBeforeDestroy = new SlickEvent('onBeforeDestroy', externalPubSub); + this.onBeforeEditCell = new SlickEvent('onBeforeEditCell', externalPubSub); + this.onBeforeFooterRowCellDestroy = new SlickEvent('onBeforeFooterRowCellDestroy', externalPubSub); + this.onBeforeHeaderCellDestroy = new SlickEvent('onBeforeHeaderCellDestroy', externalPubSub); + this.onBeforeHeaderRowCellDestroy = new SlickEvent('onBeforeHeaderRowCellDestroy', externalPubSub); + this.onBeforeSetColumns = new SlickEvent('onBeforeSetColumns', externalPubSub); + this.onBeforeSort = new SlickEvent('onBeforeSort', externalPubSub); + this.onBeforeUpdateColumns = new SlickEvent('onBeforeUpdateColumns', externalPubSub); + this.onCellChange = new SlickEvent('onCellChange', externalPubSub); + this.onCellCssStylesChanged = new SlickEvent('onCellCssStylesChanged', externalPubSub); + this.onClick = new SlickEvent('onClick', externalPubSub); + this.onColumnsReordered = new SlickEvent('onColumnsReordered', externalPubSub); + this.onColumnsDrag = new SlickEvent('onColumnsDrag', externalPubSub); + this.onColumnsResized = new SlickEvent('onColumnsResized', externalPubSub); + this.onColumnsResizeDblClick = new SlickEvent('onColumnsResizeDblClick', externalPubSub); + this.onCompositeEditorChange = new SlickEvent('onCompositeEditorChange', externalPubSub); + this.onContextMenu = new SlickEvent('onContextMenu', externalPubSub); + this.onDrag = new SlickEvent('onDrag', externalPubSub); + this.onDblClick = new SlickEvent('onDblClick', externalPubSub); + this.onDragInit = new SlickEvent('onDragInit', externalPubSub); + this.onDragStart = new SlickEvent('onDragStart', externalPubSub); + this.onDragEnd = new SlickEvent('onDragEnd', externalPubSub); + this.onFooterClick = new SlickEvent('onFooterClick', externalPubSub); + this.onFooterContextMenu = new SlickEvent('onFooterContextMenu', externalPubSub); + this.onFooterRowCellRendered = new SlickEvent('onFooterRowCellRendered', externalPubSub); + this.onHeaderCellRendered = new SlickEvent('onHeaderCellRendered', externalPubSub); + this.onHeaderClick = new SlickEvent('onHeaderClick', externalPubSub); + this.onHeaderContextMenu = new SlickEvent('onHeaderContextMenu', externalPubSub); + this.onHeaderMouseEnter = new SlickEvent('onHeaderMouseEnter', externalPubSub); + this.onHeaderMouseLeave = new SlickEvent('onHeaderMouseLeave', externalPubSub); + this.onHeaderRowCellRendered = new SlickEvent('onHeaderRowCellRendered', externalPubSub); + this.onHeaderRowMouseEnter = new SlickEvent('onHeaderRowMouseEnter', externalPubSub); + this.onHeaderRowMouseLeave = new SlickEvent('onHeaderRowMouseLeave', externalPubSub); + this.onKeyDown = new SlickEvent('onKeyDown', externalPubSub); + this.onMouseEnter = new SlickEvent('onMouseEnter', externalPubSub); + this.onMouseLeave = new SlickEvent('onMouseLeave', externalPubSub); + this.onRendered = new SlickEvent('onRendered', externalPubSub); + this.onScroll = new SlickEvent('onScroll', externalPubSub); + this.onSelectedRowsChanged = new SlickEvent('onSelectedRowsChanged', externalPubSub); + this.onSetOptions = new SlickEvent('onSetOptions', externalPubSub); + this.onActivateChangedOptions = new SlickEvent('onActivateChangedOptions', externalPubSub); + this.onSort = new SlickEvent('onSort', externalPubSub); + this.onValidationError = new SlickEvent('onValidationError', externalPubSub); + this.onViewportChanged = new SlickEvent('onViewportChanged', externalPubSub); + this.initialize(); } @@ -2988,21 +3041,21 @@ export class SlickGrid = Column, O e * @param {Boolean} [suppressColumnSet] - do we want to supress the columns set, via "setColumns()" method? (defaults to false) * @param {Boolean} [suppressSetOverflow] - do we want to suppress the call to `setOverflow` */ - setOptions(args: Partial, suppressRender?: boolean, suppressColumnSet?: boolean, suppressSetOverflow?: boolean): void { + setOptions(newOptions: Partial, suppressRender?: boolean, suppressColumnSet?: boolean, suppressSetOverflow?: boolean): void { this.prepareForOptionsChange(); - if (this._options.enableAddRow !== args.enableAddRow) { + if (this._options.enableAddRow !== newOptions.enableAddRow) { this.invalidateRow(this.getDataLength()); } // before applying column freeze, we need our viewports to be scrolled back to left to avoid misaligned column headers - if (args.frozenColumn) { + if (newOptions.frozenColumn) { this.getViewports().forEach(vp => vp.scrollLeft = 0); this.handleScroll(); // trigger scroll to realign column headers as well } const originalOptions = Utils.extend(true, {}, this._options); - this._options = Utils.extend(this._options, args); + this._options = Utils.extend(this._options, newOptions); this.trigger(this.onSetOptions, { optionsBefore: originalOptions, optionsAfter: this._options }); this.internal_setOptions(suppressRender, suppressColumnSet, suppressSetOverflow); diff --git a/packages/common/src/global-grid-options.ts b/packages/common/src/global-grid-options.ts index e87296944..dacae5f36 100644 --- a/packages/common/src/global-grid-options.ts +++ b/packages/common/src/global-grid-options.ts @@ -113,8 +113,6 @@ export const GlobalGridOptions: Partial = { defaultFilterPlaceholder: '🔎︎', defaultFilterRangeOperator: OperatorType.rangeInclusive, defaultColumnSortFieldId: 'id', - defaultComponentEventPrefix: '', - defaultSlickgridEventPrefix: '', draggableGrouping: { hideToggleAllButton: false, toggleAllButtonText: '', diff --git a/packages/common/src/interfaces/gridOption.interface.ts b/packages/common/src/interfaces/gridOption.interface.ts index bda6771d8..f3998537c 100644 --- a/packages/common/src/interfaces/gridOption.interface.ts +++ b/packages/common/src/interfaces/gridOption.interface.ts @@ -247,9 +247,6 @@ export interface GridOption { /** Default column width, is set to 80 when null */ defaultColumnWidth?: number; - /** Default prefix for Component Event names (events created in the Web Component) */ - defaultComponentEventPrefix?: string; - /** The default filter model to use when none is specified */ defaultFilter?: any; @@ -262,9 +259,6 @@ export interface GridOption { /** Default cell Formatter that will be used by the grid */ defaultFormatter?: Formatter; - /** Default prefix for SlickGrid Event names (events created in the SlickGrid and/or DataView objects) */ - defaultSlickgridEventPrefix?: string; - /** Do we have paging enabled? */ doPaging?: boolean; diff --git a/packages/event-pub-sub/src/eventPubSub.service.ts b/packages/event-pub-sub/src/eventPubSub.service.ts index 496f9bb1c..da55cc847 100644 --- a/packages/event-pub-sub/src/eventPubSub.service.ts +++ b/packages/event-pub-sub/src/eventPubSub.service.ts @@ -101,6 +101,7 @@ export class EventPubSubService implements BasePubSubService { if (delay) { return new Promise(resolve => { + clearTimeout(this._timer); this._timer = setTimeout(() => resolve(this.dispatchCustomEvent(eventNameByConvention, data, true, true)), delay); }); } else { diff --git a/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts b/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts index d86809da0..d00f862a4 100644 --- a/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts +++ b/packages/vanilla-bundle/src/components/__tests__/slick-vanilla-grid.spec.ts @@ -799,7 +799,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () const extensions = component.extensions as ExtensionList; expect(Object.keys(extensions).length).toBe(1); - expect(dataviewSpy).toHaveBeenCalledWith({ inlineFilters: false, groupItemMetadataProvider: expect.anything() }); + expect(dataviewSpy).toHaveBeenCalledWith({ inlineFilters: false, groupItemMetadataProvider: expect.anything() }, eventPubSubService); expect(sharedService.groupItemMetadataProvider instanceof SlickGroupItemMetadataProvider).toBeTruthy(); expect(sharedMetaSpy).toHaveBeenCalledWith(expect.toBeObject()); expect(mockGrid.registerPlugin).toHaveBeenCalled(); @@ -814,7 +814,7 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () component.gridOptions = { enableGrouping: true }; component.initialization(divContainer, slickEventHandler); - expect(dataviewSpy).toHaveBeenCalledWith({ inlineFilters: false, groupItemMetadataProvider: expect.anything() }); + expect(dataviewSpy).toHaveBeenCalledWith({ inlineFilters: false, groupItemMetadataProvider: expect.anything() }, eventPubSubService); expect(sharedMetaSpy).toHaveBeenCalledWith(expect.toBeObject()); expect(sharedService.groupItemMetadataProvider instanceof SlickGroupItemMetadataProvider).toBeTruthy(); expect(mockGrid.registerPlugin).toHaveBeenCalled(); @@ -1627,20 +1627,6 @@ describe('Slick-Vanilla-Grid-Bundle Component instantiated via Constructor', () expect(renderSpy).toHaveBeenCalled(); expect(updateRowSpy).toHaveBeenCalledTimes(3); }); - - it('should call "dispatchCustomEvent" when event gets trigger', () => { - const dispatchSpy = jest.spyOn(eventPubSubService, 'dispatchCustomEvent'); - const callback = jest.fn(); - - component.gridOptions = { enableFiltering: true }; - component.initialization(divContainer, slickEventHandler); - - component.eventHandler.subscribe(mockEventPubSub as any, callback); - mockGrid.onClick.notify({ rows: [1, 2, 3] } as any); - - // callback(new CustomEvent('onDblClick'), {}); - expect(dispatchSpy).toHaveBeenCalledWith('onclick', { eventData: undefined, args: { rows: [1, 2, 3] } }); - }); }); describe('setHeaderRowVisibility grid method', () => { diff --git a/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts b/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts index 33f7e1ddf..f0d72f9b2 100644 --- a/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts +++ b/packages/vanilla-bundle/src/components/slick-vanilla-grid-bundle.ts @@ -496,7 +496,7 @@ export class SlickVanillaGridBundle { this.sharedService.groupItemMetadataProvider = this.groupItemMetadataProvider; dataViewOptions = { ...dataViewOptions, groupItemMetadataProvider: this.groupItemMetadataProvider }; } - this.dataView = new SlickDataView(dataViewOptions as Partial); + this.dataView = new SlickDataView(dataViewOptions as Partial, this._eventPubSubService); this._eventPubSubService.publish('onDataviewCreated', this.dataView); } @@ -537,7 +537,7 @@ export class SlickVanillaGridBundle { this.gridOptions = { ...this.gridOptions, ...this.gridOptions.presets.pinning }; } - this.slickGrid = new SlickGrid, GridOption>>(gridContainerElm, this.dataView as SlickDataView, this._columnDefinitions, this._gridOptions); + this.slickGrid = new SlickGrid, GridOption>>(gridContainerElm, this.dataView as SlickDataView, this._columnDefinitions, this._gridOptions, this._eventPubSubService); this.sharedService.dataView = this.dataView as SlickDataView; this.sharedService.slickGrid = this.slickGrid as SlickGrid; this.sharedService.gridContainerElement = this._gridContainerElm; @@ -762,26 +762,6 @@ export class SlickVanillaGridBundle { } if (dataView && grid) { - // expose all Slick Grid Events through dispatch - for (const prop in grid) { - if (grid.hasOwnProperty(prop) && prop.startsWith('on')) { - this._eventHandler.subscribe((grid as any)[prop], (event, args) => { - const gridEventName = this._eventPubSubService.getEventNameByNamingConvention(prop, this._gridOptions?.defaultSlickgridEventPrefix ?? ''); - return this._eventPubSubService.dispatchCustomEvent(gridEventName, { eventData: event, args }); - }); - } - } - - // expose all Slick DataView Events through dispatch - for (const prop in dataView) { - if (dataView.hasOwnProperty(prop) && prop.startsWith('on')) { - this._eventHandler.subscribe((dataView as any)[prop], (event, args) => { - const dataViewEventName = this._eventPubSubService.getEventNameByNamingConvention(prop, this._gridOptions?.defaultSlickgridEventPrefix ?? ''); - return this._eventPubSubService.dispatchCustomEvent(dataViewEventName, { eventData: event, args }); - }); - } - } - // after all events are exposed // we can bind external filter (backend) when available or default onFilter (dataView) if (gridOptions.enableFiltering) {