Skip to content

Commit

Permalink
Form: refix close popup on label click (T1258881) (#28617)
Browse files Browse the repository at this point in the history
  • Loading branch information
anna-shakhova authored Dec 24, 2024
1 parent 17055b8 commit 1d09e9b
Show file tree
Hide file tree
Showing 2 changed files with 109 additions and 31 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,10 @@ import $ from '@js/core/renderer';
import { extend } from '@js/core/utils/extend';
import { captionize } from '@js/core/utils/inflector';
import { each } from '@js/core/utils/iterator';
import { isBoolean, isDefined, isFunction } from '@js/core/utils/type';
import { isDefined, isFunction } from '@js/core/utils/type';
import type { dxDropDownEditorOptions } from '@js/ui/drop_down_editor/ui.drop_down_editor';
import type { FormItemComponent } from '@js/ui/form';
import type { dxOverlayOptions } from '@js/ui/overlay';
import type { Properties as PopupProperties } from '@js/ui/popup';
import type dxTextBox from '@js/ui/text_box';

import { SIMPLE_ITEM_TYPE } from './constants';
Expand Down Expand Up @@ -167,12 +167,10 @@ export function convertToLabelMarkOptions(
};
}

// eslint-disable-next-line @typescript-eslint/naming-convention
function _getDropDownEditorOptions(
function getDropDownEditorOptions(
$parent,
editorType: FormItemComponent,
editorInputId: string,
onContentReadyExternal?: DropDownOptions['onContentReady'],
): DropDownOptions {
const isDropDownEditor = DROP_DOWN_EDITORS.includes(editorType);

Expand All @@ -181,33 +179,28 @@ function _getDropDownEditorOptions(
}

return {
onContentReady: (e) => {
const { component } = e;
// @ts-expect-error // unpublished option
onPopupInitialized: ({ component, popup }): void => {
const openOnFieldClick = component.option('openOnFieldClick') as DropDownOptions['openOnFieldClick'];
const initialHideOnOutsideClick = component.option('dropDownOptions.hideOnOutsideClick') as dxOverlayOptions<dxTextBox>['hideOnOutsideClick'];

if (openOnFieldClick) {
component.option('dropDownOptions', {
hideOnOutsideClick: (e) => {
if (isBoolean(initialHideOnOutsideClick)) {
return initialHideOnOutsideClick;
}
const initialHideOnOutsideClick = popup.option('hideOnOutsideClick') as PopupProperties['hideOnOutsideClick'];

const $target = $(e.target);
const $label = $parent.find(`label[for="${editorInputId}"]`);
const isLabelClicked = !!$target.closest($label).length;
// Do not overwrite boolean hideOnOutsideClick
if (openOnFieldClick && isFunction(initialHideOnOutsideClick)) {
const hideOnOutsideClick: PopupProperties['hideOnOutsideClick'] = (e) => {
const $target = $(e.target);
const $label = $parent.find(`label[for="${editorInputId}"]`);
const isLabelClicked = !!$target.closest($label).length;

if (!isFunction(initialHideOnOutsideClick)) {
return !isLabelClicked;
}
return !isLabelClicked && initialHideOnOutsideClick(e);
};

return !isLabelClicked && initialHideOnOutsideClick(e);
},
component.option('dropDownOptions', {
hideOnOutsideClick,
});
}

if (isFunction(onContentReadyExternal)) {
onContentReadyExternal(e);
popup.option({
hideOnOutsideClick,
});
}
},
};
Expand Down Expand Up @@ -245,7 +238,7 @@ function _convertToEditorOptions({
const stylingMode = externalEditorOptions?.stylingMode || editorStylingMode;
const useSpecificLabelOptions = EDITORS_WITH_SPECIFIC_LABELS.includes(editorType);

const dropDownEditorOptions = _getDropDownEditorOptions($parent, editorType, editorInputId, externalEditorOptions?.onContentReady);
const dropDownEditorOptions = getDropDownEditorOptions($parent, editorType, editorInputId);

const result = extend(
true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4580,15 +4580,100 @@ QUnit.test('form should be dirty when some editors are dirty', function(assert)
// NOTE: In the real environment, clicking the label triggers a click on the editor,
// toggling the popup visibility if openOnFieldClick=true.
// This assertion only takes hideOnOutsideClick into account
if(hideOnOutsideClick === false) {
assert.true(editorInstance.option('opened'), `drop down list ${openOnFieldClick ? 'is hidden by triggered input click' : 'is visible'}`);
} else {
assert.strictEqual(editorInstance.option('opened'), openOnFieldClick, `drop down list is hidden by ${openOnFieldClick ? 'triggered input click' : 'outside click'}`);
switch(hideOnOutsideClick) {
case true:
assert.false(editorInstance.option('opened'), 'drop down list is hidden by outside click');
break;
case false:
assert.true(editorInstance.option('opened'), `drop down list ${openOnFieldClick ? 'is hidden by triggered input click' : 'is visible'}`);
break;
default:
assert.strictEqual(editorInstance.option('opened'), openOnFieldClick, `drop down list is hidden by ${openOnFieldClick ? 'triggered input click' : 'outside click'}`);
}
});
});
});

QUnit.test('DropDownEditor popup must toggle on input or dropDownButton click if openOnFieldClick = true', function(assert) {
const $form = $('#form').dxForm({
formData: { CustomerID: 'VINET' },
items: [{
itemType: 'group',
colCount: 2,
items: [{
dataField: 'CustomerID',
editorType: 'dxSelectBox',
editorOptions: {
items: ['VINET', 'VALUE', 'VINS'],
value: '',
openOnFieldClick: true,
},
}],
}],
});

const $dropDownEditorInput = $form.find(`.${EDITOR_INPUT_CLASS}`);
const $dropDownButton = $form.find(`.${DROP_DOWN_EDITOR_BUTTON_CLASS}`);

pointerMock($dropDownEditorInput).click();

const editorInstance = $form.dxForm('instance').getEditor('CustomerID');

assert.true(editorInstance.option('opened'), 'drop down list is visible');

pointerMock($dropDownEditorInput).click();

assert.false(editorInstance.option('opened'), 'drop down list is hidden');

pointerMock($dropDownButton).click();

assert.true(editorInstance.option('opened'), 'drop down list is visible');

pointerMock($dropDownButton).click();

assert.false(editorInstance.option('opened'), 'drop down list is hidden');
});

QUnit.test('DropDownEditor popup must toggle on dropDownButton click if openOnFieldClick = false', function(assert) {
const $form = $('#form').dxForm({
formData: { CustomerID: 'VINET' },
items: [{
itemType: 'group',
colCount: 2,
items: [{
dataField: 'CustomerID',
editorType: 'dxSelectBox',
editorOptions: {
items: ['VINET', 'VALUE', 'VINS'],
value: '',
openOnFieldClick: false,
},
}],
}],
});

const $dropDownEditorInput = $form.find(`.${EDITOR_INPUT_CLASS}`);
const $dropDownButton = $form.find(`.${DROP_DOWN_EDITOR_BUTTON_CLASS}`);

pointerMock($dropDownEditorInput).click();

const editorInstance = $form.dxForm('instance').getEditor('CustomerID');

assert.false(editorInstance.option('opened'), 'drop down list is hidden');

pointerMock($dropDownButton).click();

assert.true(editorInstance.option('opened'), 'drop down list is visible');

pointerMock($dropDownEditorInput).click();

assert.true(editorInstance.option('opened'), 'drop down list is visible');

pointerMock($dropDownButton).click();

assert.false(editorInstance.option('opened'), 'drop down list is hidden');
});

QUnit.module('reset', () => {
[
['dxCalendar', new Date(2019, 1, 2), { dxCalendar: new Date(2019, 1, 3) } ],
Expand Down

0 comments on commit 1d09e9b

Please sign in to comment.