Skip to content
Open
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
6 changes: 2 additions & 4 deletions packages/devextreme/js/__internal/core/widget/widget.ts
Original file line number Diff line number Diff line change
Expand Up @@ -427,8 +427,7 @@ class Widget<
// eslint-disable-next-line @typescript-eslint/no-unsafe-return
keyboardListeners.forEach((listener) => listener?._keyboardHandler(options));

// eslint-disable-next-line @typescript-eslint/no-unused-expressions
onKeyboardHandled && onKeyboardHandled(options);
onKeyboardHandled?.(options);

return true;
}
Expand Down Expand Up @@ -570,13 +569,12 @@ class Widget<
this.$element().toggleClass('dx-state-independent', ignoreParentReadOnly);
}

_setWidgetOption(widgetName: string, args: Record<string, unknown>): void {
_setWidgetOption(widgetName: string, args: [string, unknown?] | [Record<string, unknown>]): void {
if (!this[widgetName]) {
return;
}

if (isPlainObject(args[0])) {
// @ts-expect-error
each(args[0], (option, value) => this._setWidgetOption(widgetName, [option, value]));

return;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { normalizeDataSourceOptions } from '../../../common/data/data_source/uti
import { extend } from '../../../core/utils/extend';
import { isDefined } from '../../../core/utils/type';

interface DataSourceType {
export interface DataSourceType {
_userData: unknown;
_pageSize: number;
dispose: () => void;
Expand Down Expand Up @@ -47,7 +47,6 @@ interface DataControllerOptions extends Record<string, unknown> {
class DataController {
private _isSharedDataSource = false;

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
private _dataSource: DataSourceType;

Expand Down Expand Up @@ -75,7 +74,6 @@ class DataController {
}

_updateDataSourceByItems(items: unknown[]): void {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
this._dataSource = new DataSource({
store: new ArrayStore({
key: this.key(),
Expand All @@ -93,7 +91,6 @@ class DataController {
this._dataSource.dispose();
}

// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
delete this._dataSource;
}
Expand Down Expand Up @@ -126,9 +123,8 @@ class DataController {
}

loadNextPage(): Promise<unknown> {
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-expect-error
// eslint-disable-next-line @typescript-eslint/restrict-plus-operands

this.pageIndex(1 + this.pageIndex());

return this.load();
Expand Down Expand Up @@ -189,7 +185,7 @@ class DataController {
}
}

updateDataSource(items: unknown[] | DataSourceType, key?: string): void {
updateDataSource(items?: unknown[] | DataSourceType, key?: string): void {
const dataSourceOptions = items ?? this.items();

if (key) {
Expand Down
2 changes: 1 addition & 1 deletion packages/devextreme/js/__internal/events/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ export const isPointerEvent = (e) => eventSource(e) === 'pointer';
export const isMouseEvent = (e) => isNativeMouseEvent(e)
|| ((isPointerEvent(e) || isDxEvent(e)) && e.pointerType === 'mouse');

export const isDxMouseWheelEvent = (e) => e && e.type === 'dxmousewheel';
export const isDxMouseWheelEvent = (e) => e?.type === 'dxmousewheel';

export const isTouchEvent = (e) => isNativeTouchEvent(e)
|| ((isPointerEvent(e) || isDxEvent(e)) && e.pointerType === 'touch');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -908,7 +908,7 @@ class DropDownEditor<
toolbarItems: this._getPopupToolbarItems(),
onPositioned: this._popupPositionedHandler.bind(this),
fullScreen: false,
// @ts-expect-error should be added on Popup level
// @ts-expect-error Should be updated on public PopupProperties level
contentTemplate: null,
_hideOnParentScrollTarget: this.$element(),
_wrapperClassExternal: DROP_DOWN_EDITOR_OVERLAY,
Expand Down Expand Up @@ -1040,7 +1040,6 @@ class DropDownEditor<
}

_setPopupOption(...args: [string, unknown?]): void {
// @ts-expect-error Should be fixed on Widget level
this._setWidgetOption('_popup', args);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,6 @@ interface DropDownListProperties extends Omit<dxDropDownListOptions<DropDownList
displayCustomValue?: boolean;
items?: Item[];
}

class DropDownList<
TProperties extends DropDownListProperties = DropDownListProperties,
> extends DropDownEditor<TProperties> {
Expand Down Expand Up @@ -417,7 +416,7 @@ class DropDownList<
}

_displayValue(item: Item): string {
// @ts-expect-error refactor DataExpressionMixin
// @ts-expect-error DataExpressionMixin must be typed
return this._displayGetter(item) as string;
}

Expand Down Expand Up @@ -696,7 +695,6 @@ class DropDownList<
): void;
_setListOption(optionName: string, value?: unknown): void;
_setListOption(...args: [string, unknown?]): void {
// @ts-expect-error fix on Widget level
this._setWidgetOption('_list', args);
}

Expand Down Expand Up @@ -1026,7 +1024,7 @@ class DropDownList<

_setSubmitValue(): void {
const { value } = this.option();
// @ts-expect-error refactor DataExpressionMixin
// @ts-expect-error DataExpressionMixin must be typed
const submitValue = this._shouldUseDisplayValue(value) ? this._displayGetter(value) : value;

this._getSubmitElement().val(submitValue);
Expand Down
81 changes: 48 additions & 33 deletions packages/devextreme/js/__internal/ui/m_autocomplete.ts
Original file line number Diff line number Diff line change
@@ -1,30 +1,41 @@
import { isCommandKeyPressed } from '@js/common/core/events/utils/index';
import registerComponent from '@js/core/component_registrator';
import registerComponent from '@js/core/component_registrator'; // couldn't change import due inconsistent typings for registerComponent
import type { dxElementWrapper } from '@js/core/renderer';
import $ from '@js/core/renderer';
import { Deferred } from '@js/core/utils/deferred';
import { extend } from '@js/core/utils/extend';
import { Deferred, type DeferredObj } from '@js/core/utils/deferred';
import type { DataSourceOptions } from '@js/data/data_source';
import type { DxEvent, PointerInteractionEvent } from '@js/events/events.types';
import type { Properties } from '@js/ui/autocomplete';
import type { ItemClickEvent, PageLoadMode } from '@js/ui/list';
import { isDefined } from '@ts/core/utils/m_type';
import type { OptionChanged } from '@ts/core/widget/types';
import { isCommandKeyPressed } from '@ts/events/utils/index';
import type { ItemCache } from '@ts/ui/drop_down_editor/drop_down_list';
import DropDownList from '@ts/ui/drop_down_editor/drop_down_list';
import type { ValueChangedEvent } from '@ts/ui/editor/editor';
import type { ListBaseProperties } from '@ts/ui/list/list.base';

const AUTOCOMPLETE_CLASS = 'dx-autocomplete';
const AUTOCOMPLETE_POPUP_WRAPPER_CLASS = 'dx-autocomplete-popup-wrapper';

export interface AutocompleteProperties extends Omit<Properties, 'onItemClick' | 'onSelectionChanged'> {}
export interface AutocompleteProperties extends Omit<
Properties, 'onItemClick' | 'onSelectionChanged'
> {

}

class Autocomplete extends DropDownList<AutocompleteProperties> {
_supportedKeys(): Record<string, (e: KeyboardEvent) => boolean> {
let item = this._list ? this._list.option('focusedElement') : null;
let item: dxElementWrapper | null = null;
if (this._list) {
const { focusedElement } = this._list.option();
item = focusedElement ? $(focusedElement) : null;
}
const parent = super._supportedKeys();
// @ts-expect-error ts-error
item = item && $(item);

return {
...parent,
upArrow(e): boolean {
// @ts-expect-error ts-error
if (parent.upArrow.apply(this, arguments) && !isCommandKeyPressed(e)) {
if (parent.upArrow.call(this, e) && !isCommandKeyPressed(e)) {
e.preventDefault();
e.stopPropagation();
if (item && !this._calcNextItem(-1)) {
Expand All @@ -35,8 +46,7 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
return true;
},
downArrow(e): boolean {
// @ts-expect-error ts-error
if (parent.downArrow.apply(this, arguments) && !isCommandKeyPressed(e)) {
if (parent.downArrow.call(this, e) && !isCommandKeyPressed(e)) {
e.preventDefault();
e.stopPropagation();
if (item && !this._calcNextItem(1)) {
Expand All @@ -54,7 +64,7 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
if (opened) {
e.preventDefault();
}
return opened;
return Boolean(opened);
},
};
}
Expand All @@ -78,17 +88,19 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
_getAriaAutocomplete(): string {
const { disabled, readOnly } = this.option();

// ?? would short-circuit on `false`, missing the other operand
// eslint-disable-next-line @typescript-eslint/prefer-nullish-coalescing
const isInputEditable = !(readOnly || disabled);

return isInputEditable ? 'list' : 'none';
}
Comment thread
vorobey marked this conversation as resolved.

_displayGetterExpr() {
return this.option('valueExpr');
_displayGetterExpr(): undefined | string | ((item: unknown) => string | number | boolean) {
const { valueExpr } = this.option();
return valueExpr;
}

_closeOutsideDropDownHandler({ target }): boolean {
_closeOutsideDropDownHandler({ target }: DxEvent<PointerInteractionEvent>): boolean {
return !$(target).closest(this.$element()).length;
}

Expand All @@ -103,18 +115,19 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
return `${super._popupWrapperClass()} ${AUTOCOMPLETE_POPUP_WRAPPER_CLASS}`;
}

_listConfig() {
return extend(super._listConfig(), {
pageLoadMode: 'none',
onSelectionChanged: (e) => {
_listConfig(): ListBaseProperties {
return {
...super._listConfig(),
pageLoadMode: 'none' as PageLoadMode,
onSelectionChanged: (e): void => {
this._setSelectedItem(e.addedItems[0]);
},
});
};
}

_listItemClickHandler(e) {
_listItemClickHandler(e: ItemClickEvent): void {
this._saveValueChangeEvent(e.event);
// @ts-expect-error ts-error
// @ts-expect-error DataExpressionMixin must be typed
const value = this._displayGetter(e.itemData);
this.option('value', value);
this.close();
Expand All @@ -129,28 +142,32 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
super._setListDataSource();
}

_refreshSelected(): void {}
_refreshSelected(): void {
// Autocomplete has no persistent selection state — suppress parent behavior
// _refreshSelected is called in parent, so we need to override here
// hence we don't need this functionality in Autocomplete
}

_searchCanceled(): void {
super._searchCanceled();
this.close();
}

_loadItem(value, cache) {
_loadItem(value: unknown, cache?: ItemCache): DeferredObj<unknown> {
const selectedItem = this._getItemFromPlain(value, cache);

return Deferred().resolve(selectedItem).promise();
return Deferred().resolve(selectedItem as unknown);
}

_dataSourceOptions() {
_dataSourceOptions(): DataSourceOptions {
const { maxItemCount } = this.option();
return {
paginate: true,
pageSize: maxItemCount,
};
}

_searchDataSource(searchValue): void {
_searchDataSource(searchValue: string): void {
const { maxItemCount } = this.option();
if (isDefined(maxItemCount)) {
this._dataSource.pageSize(maxItemCount);
Expand All @@ -166,12 +183,11 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
}
}

// eslint-disable-next-line class-methods-use-this
_renderValueEventName(): string {
return 'input keyup';
}

_valueChangeEventHandler(e): void {
_valueChangeEventHandler(e: ValueChangedEvent): void {
const value = this._input().val() || null;
return super._valueChangeEventHandler(e, value);
}
Expand All @@ -184,11 +200,10 @@ class Autocomplete extends DropDownList<AutocompleteProperties> {
this._setDefaultAria();
break;
case 'maxItemCount':
// @ts-expect-error ts-error
this._searchDataSource();
this._searchDataSource(this._searchValue());
break;
case 'valueExpr':
// @ts-expect-error ts-error
// @ts-expect-error DataExpressionMixin must be typed
this._compileDisplayGetter();
this._setListOption('displayExpr', this._displayGetterExpr());
super._optionChanged(args);
Expand Down
Loading
Loading