Skip to content

Commit

Permalink
DataHelper: try extending the component from mixin instead of using `…
Browse files Browse the repository at this point in the history
…inclide`
  • Loading branch information
EugeniyKiyashko committed Jan 24, 2025
1 parent a082e62 commit acefb7e
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 27 deletions.
26 changes: 15 additions & 11 deletions packages/devextreme/js/__internal/data/m_data_helper.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
import { DataSource } from '@js/common/data/data_source/data_source';
import { normalizeDataSourceOptions } from '@js/common/data/data_source/utils';
import { extend } from '@js/core/utils/extend';
import type { Controller } from '@ts/grids/grid_core/m_modules';
import type { ModuleType } from '@ts/grids/grid_core/m_types';
import DataController from '@ts/ui/collection/m_data_controller';

const DATA_SOURCE_OPTIONS_METHOD = '_dataSourceOptions';
Expand All @@ -13,7 +11,8 @@ const DATA_SOURCE_FROM_URL_LOAD_MODE_METHOD = '_dataSourceFromUrlLoadMode';
const SPECIFIC_DATA_SOURCE_OPTION = '_getSpecificDataSourceOption';
const NORMALIZE_DATA_SOURCE = '_normalizeDataSource';

export const DataHelperMixin = <T extends ModuleType<Controller>>(Base: T) => class DataHelperMixin extends Base {
export type Constructor<T> = (new (...args: any[]) => T);
export const DataHelperMixin = <T extends Constructor<object>>(Base: T) => class DataHelperMixin extends Base {
public _dataSource: any;

protected _dataController: any;
Expand All @@ -31,6 +30,7 @@ export const DataHelperMixin = <T extends ModuleType<Controller>>(Base: T) => cl
private readonly _dataSourceType: any;

public postCtor() {
// @ts-expect-error ts-error
this.on('disposing', () => {
this._disposeDataSource();
});
Expand All @@ -41,9 +41,11 @@ export const DataHelperMixin = <T extends ModuleType<Controller>>(Base: T) => cl
this._loadDataSource();
}

protected _initDataSource() {
protected _initDataSource(): void {
let dataSourceOptions = SPECIFIC_DATA_SOURCE_OPTION in this
? (this[SPECIFIC_DATA_SOURCE_OPTION] as any)()
// @ts-expect-error ts-error
? this[SPECIFIC_DATA_SOURCE_OPTION]()
// @ts-expect-error ts-error
: this.option('dataSource');

let widgetDataSourceOptions;
Expand All @@ -57,29 +59,33 @@ export const DataHelperMixin = <T extends ModuleType<Controller>>(Base: T) => cl
this._dataSource = dataSourceOptions;
} else {
widgetDataSourceOptions = DATA_SOURCE_OPTIONS_METHOD in this
? (this[DATA_SOURCE_OPTIONS_METHOD] as any)()
// @ts-expect-error ts-error
? this[DATA_SOURCE_OPTIONS_METHOD]()
: {};

dataSourceType = this._dataSourceType ? this._dataSourceType() : DataSource;

dataSourceOptions = normalizeDataSourceOptions(dataSourceOptions, {
fromUrlLoadMode: (DATA_SOURCE_FROM_URL_LOAD_MODE_METHOD in this) && (this[DATA_SOURCE_FROM_URL_LOAD_MODE_METHOD] as any)(),
// @ts-expect-error ts-error
fromUrlLoadMode: (DATA_SOURCE_FROM_URL_LOAD_MODE_METHOD in this) && this[DATA_SOURCE_FROM_URL_LOAD_MODE_METHOD](),
});

// eslint-disable-next-line new-cap
this._dataSource = new dataSourceType(extend(true, {}, widgetDataSourceOptions, dataSourceOptions));
}

if (NORMALIZE_DATA_SOURCE in this) {
this._dataSource = (this[NORMALIZE_DATA_SOURCE] as any)(this._dataSource);
// @ts-expect-error ts-error
this._dataSource = this[NORMALIZE_DATA_SOURCE](this._dataSource);
}

this._addDataSourceHandlers();
this._initDataController();
}
}

private _initDataController() {
protected _initDataController() {
// @ts-expect-error
const dataController = this.option?.('_dataController');
const dataSource = this._dataSource;

Expand Down Expand Up @@ -183,5 +189,3 @@ export const DataHelperMixin = <T extends ModuleType<Controller>>(Base: T) => cl
return this._dataSource || null;
}
};

export default DataHelperMixin;
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ import { getOuterHeight, getOuterWidth } from '@js/core/utils/size';
import { findTemplates } from '@js/core/utils/template_manager';
import { isDefined, isFunction, isPlainObject } from '@js/core/utils/type';
import type { DataSourceOptions } from '@js/data/data_source';
import DataHelperMixin from '@js/data_helper';
import type {
Cancelable, DxEvent, EventInfo, ItemInfo,
} from '@js/events';
Expand All @@ -35,6 +34,7 @@ import { focusable } from '@js/ui/widget/selectors';
import { getPublicElement } from '@ts/core/m_element';
import type { OptionChanged } from '@ts/core/widget/types';
import Widget from '@ts/core/widget/widget';
import { DataHelperMixin } from '@ts/data/m_data_helper';
import CollectionWidgetItem from '@ts/ui/collection/m_item';

const COLLECTION_CLASS = 'dx-collection';
Expand Down Expand Up @@ -91,7 +91,11 @@ export interface CollectionWidgetBaseProperties<

focusOnSelectedItem?: boolean;

encodeNoDataText?: boolean;

_itemAttributes?: Record<string, string>;

selectOnFocus?: boolean;
}

class CollectionWidget<
Expand All @@ -101,7 +105,7 @@ class CollectionWidget<
TItem extends ItemLike = any,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
TKey = any,
> extends Widget<TProperties> {
> extends DataHelperMixin(Widget)<TProperties> {
private _focusedItemId?: string;

// eslint-disable-next-line no-restricted-globals
Expand All @@ -121,6 +125,8 @@ class CollectionWidget<

_itemFocusHandler?: () => void;

onFocusedItemChanged?: (event?: Partial<EventInfo<unknown> & ItemInfo<TItem>>) => void;

_inkRipple?: {
showWave: (config: {
element: dxElementWrapper;
Expand Down Expand Up @@ -234,14 +240,12 @@ class CollectionWidget<

_init(): void {
this._compileDisplayGetter();
// @ts-expect-error ts-error
this._initDataController();
super._init();

this._activeStateUnit = `.${ITEM_CLASS}`;

this._cleanRenderedItems();
// @ts-expect-error ts-error
this._refreshDataSource();
}

Expand Down Expand Up @@ -575,7 +579,7 @@ class CollectionWidget<
this._updateFocusedItemState($target, true);
// @ts-expect-error ts-error
this.onFocusedItemChanged(this.getFocusedItemId());
// @ts-expect-error ts-error

const { selectOnFocus } = this.option();
const isTargetDisabled = this._isDisabled($target);

Expand Down Expand Up @@ -683,7 +687,6 @@ class CollectionWidget<
this._invalidate();
break;
case 'dataSource':
// @ts-expect-error ts-error
this._refreshDataSource();
// @ts-expect-error ts-error
this._renderEmptyMessage();
Expand All @@ -709,7 +712,6 @@ class CollectionWidget<
this._attachContextMenuEvent();
break;
case 'onFocusedItemChanged':
// @ts-expect-error ts-error
this.onFocusedItemChanged = this._createActionByOption('onFocusedItemChanged');
break;
case 'selectOnFocus':
Expand Down Expand Up @@ -742,7 +744,6 @@ class CollectionWidget<

_loadNextPage(): Promise<unknown> {
this._expectNextPageLoading();
// @ts-expect-error ts-error
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
return this._dataController.loadNextPage();
}
Expand Down Expand Up @@ -866,7 +867,6 @@ class CollectionWidget<

_initMarkup(): void {
super._initMarkup();
// @ts-expect-error ts-error
this.onFocusedItemChanged = this._createActionByOption('onFocusedItemChanged');

this.$element().addClass(COLLECTION_CLASS);
Expand Down Expand Up @@ -1355,8 +1355,8 @@ class CollectionWidget<
_renderEmptyMessage(items: TItem[]): void {
// eslint-disable-next-line no-param-reassign
items = items || this.option('items');
const noDataText = this.option('noDataText');
// @ts-expect-error ts-error
const { noDataText } = this.option();

// eslint-disable-next-line @typescript-eslint/prefer-optional-chain
const hideNoData = !noDataText || (items && items.length) || this._dataController.isLoading();

Expand All @@ -1371,11 +1371,11 @@ class CollectionWidget<
this._$noData = this._$noData ?? $('<div>').addClass('dx-empty-message');
this._$noData.appendTo(this._emptyMessageContainer());

if (this.option('encodeNoDataText')) {
// @ts-expect-error ts-error
const { encodeNoDataText } = this.option();

if (encodeNoDataText) {
this._$noData.text(noDataText);
} else {
// @ts-expect-error ts-error
this._$noData.html(noDataText);
}
}
Expand Down Expand Up @@ -1484,7 +1484,7 @@ class CollectionWidget<
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
(CollectionWidget as any).include(DataHelperMixin);
// (CollectionWidget as any).include(DataHelperMixin);

// @ts-expect-error ts-error
CollectionWidget.ItemClass = CollectionWidgetItem;
Expand Down
1 change: 0 additions & 1 deletion packages/devextreme/js/__internal/ui/menu/m_menu.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,7 +427,6 @@ class Menu extends MenuBase {
});

return extend(menuOptions, {
// @ts-expect-error
dataSource: this.getDataSource(),
animationEnabled: !!this.option('animation'),
onItemClick: this._treeviewItemClickHandler.bind(this),
Expand Down

0 comments on commit acefb7e

Please sign in to comment.