Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

perf: provide PubSub to SlickGrid/DataView avoid looping all events #401

Merged
merged 1 commit into from
Aug 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 21 additions & 57 deletions src/slickgrid-react/components/slickgrid-react.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -76,12 +76,6 @@ interface State {
paginationService: PaginationService;
}

class CustomEventPubSubService extends EventPubSubService {
set elementSource(value: Element) {
this._elementSource = value;
}
}

export class SlickgridReact<TData = any> extends React.Component<SlickgridReactProps, State> {
protected _mounted = false;
protected setStateValue(key: string, value: any, callback?: () => void): void {
Expand Down Expand Up @@ -268,22 +262,22 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
this._gridOptions = this.mergeGridOptions(props.gridOptions || {});

// initialize and assign all Service Dependencies
this._eventPubSubService = this.props.externalServices?.eventPubSubService ?? new CustomEventPubSubService();
this._eventPubSubService = new EventPubSubService();
this._eventPubSubService.eventNamingStyle = EventNamingStyle.camelCase;

this.backendUtilityService = this.props.externalServices?.backendUtilityService ?? new BackendUtilityService();
this.gridEventService = this.props.externalServices?.gridEventService ?? new GridEventService();
this.sharedService = this.props.externalServices?.sharedService ?? new SharedService();
this.collectionService = this.props.externalServices?.collectionService ?? new CollectionService(this.props.translaterService);
this.extensionUtility = this.props.externalServices?.extensionUtility ?? new ExtensionUtility(this.sharedService, this.backendUtilityService, this.props.translaterService);
this.backendUtilityService = new BackendUtilityService();
this.gridEventService = new GridEventService();
this.sharedService = new SharedService();
this.collectionService = new CollectionService(this.props.translaterService);
this.extensionUtility = new ExtensionUtility(this.sharedService, this.backendUtilityService, this.props.translaterService);
this.filterFactory = new FilterFactory(slickgridConfig, this.props.translaterService, this.collectionService);
this.filterService = this.props.externalServices?.filterService ?? new FilterService(this.filterFactory as any, this._eventPubSubService, this.sharedService, this.backendUtilityService);
this.resizerService = this.props.externalServices?.resizerService ?? new ResizerService(this._eventPubSubService);
this.sortService = this.props.externalServices?.sortService ?? new SortService(this.sharedService, this._eventPubSubService, this.backendUtilityService);
this.treeDataService = this.props.externalServices?.treeDataService ?? new TreeDataService(this._eventPubSubService, this.sharedService, this.sortService);
this.paginationService = this.props.externalServices?.paginationService ?? new PaginationService(this._eventPubSubService, this.sharedService, this.backendUtilityService);
this.filterService = new FilterService(this.filterFactory as any, this._eventPubSubService, this.sharedService, this.backendUtilityService);
this.resizerService = new ResizerService(this._eventPubSubService);
this.sortService = new SortService(this.sharedService, this._eventPubSubService, this.backendUtilityService);
this.treeDataService = new TreeDataService(this._eventPubSubService, this.sharedService, this.sortService);
this.paginationService = new PaginationService(this._eventPubSubService, this.sharedService, this.backendUtilityService);

this.extensionService = this.props.externalServices?.extensionService ?? new ExtensionService(
this.extensionService = new ExtensionService(
this.extensionUtility,
this.filterService,
this._eventPubSubService,
Expand All @@ -294,9 +288,9 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
() => this.gridService
);

this.gridStateService = this.props.externalServices?.gridStateService ?? new GridStateService(this.extensionService, this.filterService, this._eventPubSubService, this.sharedService, this.sortService, this.treeDataService);
this.gridService = this.props.externalServices?.gridService ?? new GridService(this.gridStateService, this.filterService, this._eventPubSubService, this.paginationService, this.sharedService, this.sortService, this.treeDataService);
this.groupingService = this.props.externalServices?.groupingAndColspanService ?? new GroupingAndColspanService(this.extensionUtility, this._eventPubSubService);
this.gridStateService = new GridStateService(this.extensionService, this.filterService, this._eventPubSubService, this.sharedService, this.sortService, this.treeDataService);
this.gridService = new GridService(this.gridStateService, this.filterService, this._eventPubSubService, this.paginationService, this.sharedService, this.sortService, this.treeDataService);
this.groupingService = new GroupingAndColspanService(this.extensionUtility, this._eventPubSubService);

this.serviceList = [
this.extensionService,
Expand Down Expand Up @@ -358,13 +352,13 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP

componentDidMount() {
this._mounted = true;
if (this._elm && this._eventPubSubService instanceof CustomEventPubSubService) {
(this._eventPubSubService as CustomEventPubSubService).elementSource = this._elm;
if (this._elm && this._eventPubSubService instanceof EventPubSubService) {
this._eventPubSubService.elementSource = this._elm;

// React doesn't play well with Custom Events & also the render is called after the constructor which brings a second problem
// to fix both issues, we need to do the following:
// loop through all component and subscribe to all props that startsWith "on", assuming they are custom event
// and call their listener with event is dispatching
// loop through all component props and subscribe to the ones that startsWith "on", we'll assume that it's the custom events
// we'll and call their listeners when events are dispatching
for (const prop in this.props) {
if (prop.startsWith('on')) {
this.subscriptions.push(
Expand Down Expand Up @@ -450,7 +444,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
this.sharedService.groupItemMetadataProvider = this.groupItemMetadataProvider;
dataViewOptions = { ...dataViewOptions, groupItemMetadataProvider: this.groupItemMetadataProvider };
}
this.dataView = new SlickDataView<TData>(dataViewOptions as Partial<DataViewOption>);
this.dataView = new SlickDataView<TData>(dataViewOptions as Partial<DataViewOption>, this._eventPubSubService);
this._eventPubSubService.publish('onDataviewCreated', this.dataView);
}

Expand Down Expand Up @@ -480,7 +474,7 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
}

// build SlickGrid Grid, also user might optionally pass a custom dataview (e.g. remote model)
this.grid = new SlickGrid(`#${this.props.gridId}`, this.props.customDataView || this.dataView, this._columnDefinitions, this._gridOptions);
this.grid = new SlickGrid(`#${this.props.gridId}`, this.props.customDataView || this.dataView, this._columnDefinitions, this._gridOptions, this._eventPubSubService);
this.sharedService.dataView = this.dataView;
this.sharedService.slickGrid = this.grid;
this.sharedService.gridContainerElement = this._elm as HTMLDivElement;
Expand Down Expand Up @@ -780,36 +774,6 @@ export class SlickgridReact<TData = any> extends React.Component<SlickgridReactP
}

if (dataView && grid) {
const slickgridEventPrefix = '';

// expose all Slick Grid Events through dispatch
for (const prop in grid) {
if (grid.hasOwnProperty(prop) && prop.startsWith('on')) {
const gridEventName = this._eventPubSubService.getEventNameByNamingConvention(prop, slickgridEventPrefix);
this._eventHandler.subscribe((grid as any)[prop], (event, args: any) => {
if (this.props.hasOwnProperty(prop)) {
const callback = this.props[prop as keyof SlickgridReactProps];
return typeof callback === 'function' && callback(new CustomEvent(gridEventName, { detail: { eventData: event, args } }));
}
return true;
});
}
}

// 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: any) => {
const dataViewEventName = this._eventPubSubService.getEventNameByNamingConvention(prop, slickgridEventPrefix);
if (this.props.hasOwnProperty(prop)) {
const callback = this.props[prop as keyof SlickgridReactProps];
return typeof callback === 'function' && callback(new CustomEvent(dataViewEventName, { detail: { eventData: event, args } }));
}
return true;
});
}
}

// on cell click, mainly used with the columnDef.action callback
this.gridEventService.bindOnBeforeEditCell(grid);
this.gridEventService.bindOnCellChange(grid);
Expand Down
34 changes: 0 additions & 34 deletions src/slickgrid-react/components/slickgridReactProps.ts
Original file line number Diff line number Diff line change
@@ -1,28 +1,13 @@
import type {
BackendUtilityService,
CollectionService,
Column,
ContainerService,
ExtensionList,
ExtensionService,
ExtensionUtility,
FilterService,
GridOption,
GridEventService,
GridService,
GridStateService,
GroupingAndColspanService,
Pagination,
PaginationService,
ResizerService,
RxJsFacade,
SharedService,
SlickControlList,
SlickDataView,
SlickPluginList,
SortService,
TranslaterService,
TreeDataService,
OnActiveCellChangedEventArgs,
DragRowMove,
OnAddNewRowEventArgs,
Expand Down Expand Up @@ -68,7 +53,6 @@ import type {
PagingInfo,
SlickGrid,
} from '@slickgrid-universal/common';
import type { EventPubSubService } from '@slickgrid-universal/event-pub-sub';
import type { SlickgridReactInstance } from '../models';
import type { ReactUtilService } from '../services';

Expand All @@ -78,24 +62,6 @@ export interface SlickgridReactProps {
reactUtilService: ReactUtilService;
containerService: ContainerService;
translaterService: TranslaterService;
externalServices?: {
backendUtilityService?: BackendUtilityService,
collectionService?: CollectionService,
eventPubSubService?: EventPubSubService,
extensionService?: ExtensionService,
extensionUtility?: ExtensionUtility,
filterService?: FilterService,
gridEventService?: GridEventService,
gridService?: GridService,
gridStateService?: GridStateService,
groupingAndColspanService?: GroupingAndColspanService,
paginationService?: PaginationService,
resizerService?: ResizerService,
rxjs?: RxJsFacade,
sharedService?: SharedService,
sortService?: SortService,
treeDataService?: TreeDataService,
}
customDataView?: SlickDataView;
dataset: any[];
datasetHierarchical?: any[] | null;
Expand Down