Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import type { dxElementWrapper } from '@js/core/renderer';
import $ from '@js/core/renderer';
import type { DxEvent } from '@js/events';
import type { OptionChanged } from '@ts/core/widget/types';
import type { EditorProperties } from '@ts/ui/editor/editor';
import type { EditorProperties, ValueChangedEvent } from '@ts/ui/editor/editor';
import Editor from '@ts/ui/editor/editor';

const RADIO_BUTTON_CLASS = 'dx-radiobutton';
Expand All @@ -24,11 +24,10 @@ class RadioButton extends Editor {

_clickAction?: (event?: Record<string, unknown>) => void;

// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
_supportedKeys(): Record<string, (e: KeyboardEvent) => void | boolean> {
const click = function (e) {
_supportedKeys(): Record<string, (e: KeyboardEvent) => void> {
const click = (e: KeyboardEvent): void => {
e.preventDefault();
this._clickAction({ event: e });
this._clickAction?.({ event: e });
};
return {
...super._supportedKeys(),
Expand Down Expand Up @@ -70,10 +69,12 @@ class RadioButton extends Editor {
}

_initMarkup(): void {
const { value } = this.option();

super._initMarkup();

this._renderIcon();
this._renderCheckedState(this.option('value'));
this._renderCheckedState(value);
this._renderClick();
this.setAria('role', 'radio');
}
Expand All @@ -85,7 +86,7 @@ class RadioButton extends Editor {
this.$element().append(this._$icon);
}

_renderCheckedState(checked): void {
_renderCheckedState(checked: boolean): void {
this.$element()
.toggleClass(RADIO_BUTTON_CHECKED_CLASS, checked)
.find(`.${RADIO_BUTTON_ICON_CLASS}`)
Expand All @@ -94,10 +95,9 @@ class RadioButton extends Editor {
}

_renderClick(): void {
// @ts-expect-error ts-error
const eventName = addNamespace(clickEventName, this.NAME);
const eventName = addNamespace(clickEventName, this.NAME ?? '');

this._clickAction = this._createAction((args): void => {
this._clickAction = this._createAction((args: { event: ValueChangedEvent }): void => {
this._clickHandler(args.event);
});

Expand All @@ -107,7 +107,7 @@ class RadioButton extends Editor {
});
}

_clickHandler(e): void {
_clickHandler(e: ValueChangedEvent): void {
this._saveValueChangeEvent(e);
this.option('value', true);
this._saveValueChangeEvent(undefined);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { dxElementWrapper } from '@js/core/renderer';
import $ from '@js/core/renderer';
import { deferRender } from '@js/core/utils/common';
import { extend } from '@js/core/utils/extend';
import type { DxEvent } from '@js/events';
import DataExpressionMixin from '@js/ui/editor/ui.data_expression';
import type { CollectionWidgetBaseProperties } from '@ts/ui/collection/collection_widget.base';
import CollectionWidget from '@ts/ui/collection/collection_widget.edit';
Expand All @@ -26,12 +26,13 @@ class RadioCollection extends CollectionWidget<Properties> {
}

_getDefaultOptions(): Properties {
const defaultOptions = super._getDefaultOptions();

// @ts-expect-error
return extend(defaultOptions, DataExpressionMixin._dataExpressionDefaultOptions(), {
return {
...super._getDefaultOptions(),
// @ts-expect-error DataExpressionMixin._dataExpressionDefaultOptions()
// should be added to the type
...DataExpressionMixin._dataExpressionDefaultOptions(),
_itemAttributes: { role: 'radio' },
});
} as Properties;
}

_initMarkup(): void {
Expand Down Expand Up @@ -83,22 +84,21 @@ class RadioCollection extends CollectionWidget<Properties> {
this._renderContent();
}

_supportedKeys(): Record<string, (e: KeyboardEvent) => void> {
_supportedKeys(): Record<string, (e: DxEvent<KeyboardEvent>) => void> {
const parent = super._supportedKeys();

return extend({}, parent, {
enter(e) {
return {
...parent,
enter(e: DxEvent<KeyboardEvent>): void {
e.preventDefault();
// @ts-expect-error
return parent.enter.apply(this, arguments);
parent.enter?.apply(this, [e]);
},

space(e) {
space(e: DxEvent<KeyboardEvent>): void {
e.preventDefault();
// @ts-expect-error
return parent.space.apply(this, arguments);
parent.space?.apply(this, [e]);
},
});
};
}

_itemElements(): dxElementWrapper {
Expand Down
112 changes: 57 additions & 55 deletions packages/devextreme/js/__internal/ui/radio_group/m_radio_group.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@ import type { dxElementWrapper } from '@js/core/renderer';
import $ from '@js/core/renderer';
import type { DeferredObj } from '@js/core/utils/deferred';
import { Deferred } from '@js/core/utils/deferred';
import { extend } from '@js/core/utils/extend';
import { isDefined } from '@js/core/utils/type';
import type { ItemInfo, NativeEventInfo } from '@js/events';
import type { ItemLike } from '@js/ui/collection/ui.collection_widget.base';
import DataExpressionMixin from '@js/ui/editor/ui.data_expression';
import type { Properties } from '@js/ui/radio_group';
import type { OptionChanged } from '@ts/core/widget/types';
import type { EditorProperties, UnresolvedEvents } from '@ts/ui/editor/editor';
import type { EditorProperties, UnresolvedEvents, ValueChangedEvent } from '@ts/ui/editor/editor';
import Editor from '@ts/ui/editor/editor';

import RadioCollection from './m_radio_collection';
Expand All @@ -28,21 +29,18 @@ interface RadioGroupProperties extends Properties,
class RadioGroup extends Editor<RadioGroupProperties> {
private _radios?: RadioCollection;

private _areRadiosCreated!: DeferredObj<unknown>;
private _areRadiosCreated!: DeferredObj<void>;

private _$submitElement!: dxElementWrapper;

// eslint-disable-next-line class-methods-use-this
_dataSourceOptions(): { paginate: boolean } {
return { paginate: false };
}

// eslint-disable-next-line class-methods-use-this
protected _activeStateUnit(): string {
return `.${RADIO_BUTTON_CLASS}`;
}

// eslint-disable-next-line class-methods-use-this
protected _feedbackHideTimeout(): number {
return RADIO_FEEDBACK_HIDE_TIMEOUT;
}
Expand All @@ -63,32 +61,38 @@ class RadioGroup extends Editor<RadioGroupProperties> {
}]);
}

// @ts-expect-error
// @ts-expect-error widget.ts _fireContentReadyAction should accept an optional `force` parameter
_fireContentReadyAction(force: boolean): void {
force && super._fireContentReadyAction();
if (!force) {
return;
}

// eslint-disable-next-line @typescript-eslint/no-floating-promises
super._fireContentReadyAction();
}

_focusTarget() {
_focusTarget(): dxElementWrapper {
return this.$element();
}

_getAriaTarget() {
_getAriaTarget(): dxElementWrapper {
return this.$element();
}

_getDefaultOptions() {
const defaultOptions = super._getDefaultOptions();

// @ts-expect-error
return extend(defaultOptions, extend(DataExpressionMixin._dataExpressionDefaultOptions(), {
_getDefaultOptions(): RadioGroupProperties {
return {
...super._getDefaultOptions(),
// @ts-expect-error DataExpressionMixin should expose _dataExpressionDefaultOptions as a
// typed static method
...DataExpressionMixin._dataExpressionDefaultOptions(),
hoverStateEnabled: true,
activeStateEnabled: true,
layout: 'vertical',
}));
} as RadioGroupProperties;
}

_getItemValue(item) {
// @ts-expect-error
_getItemValue(item: ItemLike): unknown {
// @ts-expect-error valueGetter is injected by DataExpressionMixin
return this._valueGetter ? this._valueGetter(item) : item.text;
}

Expand All @@ -99,7 +103,7 @@ class RadioGroup extends Editor<RadioGroupProperties> {
_init(): void {
super._init();

// @ts-expect-error
// @ts-expect-error _initDataExpressions is injected by DataExpressionMixin
this._initDataExpressions();
}

Expand All @@ -112,28 +116,29 @@ class RadioGroup extends Editor<RadioGroupProperties> {
super._initMarkup();
}

_itemClickHandler({ itemElement, event, itemData }): void {
// @ts-expect-error
if (this.itemElements().is(itemElement)) {
_itemClickHandler({ itemElement, event, itemData }:
NativeEventInfo<RadioCollection, MouseEvent | PointerEvent> & ItemInfo): void {
if (this.itemElements()?.is($(itemElement))) {
const { value } = this.option();
const newValue = this._getItemValue(itemData);

if (newValue !== this.option('value')) {
this._saveValueChangeEvent(event);
if (newValue !== value) {
this._saveValueChangeEvent(event as unknown as ValueChangedEvent);
this.option('value', newValue);
}
}
}

_getSelectedItemKeys(value) {
// @ts-expect-error
const isNullSelectable = this.option('valueExpr') !== 'this';
const shouldSelectValue = isNullSelectable && value === null || isDefined(value);
_getSelectedItemKeys(value: unknown): unknown[] {
const { valueExpr } = this.option();
const isNullSelectable = valueExpr !== 'this';
const shouldSelectValue = (isNullSelectable && value === null) || isDefined(value);

return shouldSelectValue ? [value] : [];
}

_setSelection(currentValue): void {
// @ts-expect-error
_setSelection(currentValue: unknown): void {
// @ts-expect-error _unwrappedValue is injected by DataExpressionMixin
const value = this._unwrappedValue(currentValue);
this._setCollectionWidgetOption('selectedItemKeys', this._getSelectedItemKeys(value));
}
Expand All @@ -147,7 +152,7 @@ class RadioGroup extends Editor<RadioGroupProperties> {

_optionChanged(args: OptionChanged<RadioGroupProperties>): void {
const { name, value } = args;
// @ts-expect-error
// @ts-expect-error _dataExpressionOptionChanged is injected by DataExpressionMixin
this._dataExpressionOptionChanged(args);

switch (name) {
Expand All @@ -164,7 +169,7 @@ class RadioGroup extends Editor<RadioGroupProperties> {
this._setCollectionWidgetOption(name, value);
break;
case 'valueExpr':
// @ts-expect-error
// @ts-expect-error _getCollectionKeyExpr is injected by DataExpressionMixin
this._setCollectionWidgetOption('keyExpr', this._getCollectionKeyExpr());
break;
case 'value':
Expand All @@ -173,7 +178,7 @@ class RadioGroup extends Editor<RadioGroupProperties> {
super._optionChanged(args);
break;
case 'items':
this._setSelection(this.option('value'));
this._setSelection(this.option().value);
break;
case 'itemTemplate':
case 'displayExpr':
Expand Down Expand Up @@ -215,21 +220,20 @@ class RadioGroup extends Editor<RadioGroupProperties> {
onInitialized: ({ component }) => {
this._radios = component;
},
// eslint-disable-next-line @typescript-eslint/no-unused-vars
onContentReady: (e) => {
onContentReady: () => {
this._fireContentReadyAction(true);
},
// @ts-expect-error
onItemClick: this._itemClickHandler.bind(this),
displayExpr,
accessKey,
// @ts-expect-error
// @ts-expect-error _dataSource is injected by DataExpressionMixin
dataSource: this._dataSource,
focusStateEnabled,
itemTemplate,
// @ts-expect-error
// @ts-expect-error _getCollectionKeyExpr is injected by DataExpressionMixin
keyExpr: this._getCollectionKeyExpr(),
noDataText: '',
// @ts-expect-error scrollingEnabled is absent from CollectionWidgetProperties
scrollingEnabled: false,
selectByClick: false,
selectionMode: 'single',
Expand All @@ -249,35 +253,33 @@ class RadioGroup extends Editor<RadioGroupProperties> {

_setOptionsByReference(): void {
super._setOptionsByReference();
extend(this._optionsByReference, { value: true });
this._optionsByReference = { ...this._optionsByReference, value: true };
}

_setSubmitValue(value?: unknown): void {
value = value ?? this.option('value');
// @ts-expect-error
const submitValue = this.option('valueExpr') === 'this'
// @ts-expect-error
? this._displayGetter(value)
: value;
const { valueExpr, value: optionValue } = this.option();
const resolvedValue = value ?? optionValue;

this._$submitElement.val(submitValue);
}
const submitValue = valueExpr === 'this'
// @ts-expect-error _displayGetter is injected by DataExpressionMixin
? this._displayGetter(resolvedValue)
: resolvedValue;

// eslint-disable-next-line @typescript-eslint/no-unused-vars
_setCollectionWidgetOption(name: string, value: unknown): void {
// @ts-expect-error
this._$submitElement.val(submitValue as string | number | undefined);
}

this._areRadiosCreated.done(this._setWidgetOption.bind(this, '_radios', arguments));
_setCollectionWidgetOption(...args: [string, unknown]): void {
// @ts-expect-error widget._setWidgetOption args should be typed as ArrayLike<unknown>
this._areRadiosCreated.done(this._setWidgetOption.bind(this, '_radios', args));
}

_updateItemsSize(): void {
const { layout } = this.option();
const { layout, items } = this.option();

if (layout === 'horizontal') {
this.itemElements()?.css('height', 'auto');
} else {
// @ts-expect-error
const itemsCount = this.option('items').length;
const itemsCount = (items ?? []).length;

this.itemElements()?.css('height', `${100 / itemsCount}%`);
}
Expand All @@ -291,7 +293,7 @@ class RadioGroup extends Editor<RadioGroupProperties> {
return this._radios?._itemElements();
}
}
// @ts-expect-error
// @ts-expect-error Widget base class should define a typed static include() method
RadioGroup.include(DataExpressionMixin);

registerComponent('dxRadioGroup', RadioGroup);
Expand Down
Loading