fix: Fixed the multiselect issue on add new row and edit on validation onClick

This commit is contained in:
Kavin Venkatachalam 2025-03-11 16:53:07 +05:30
parent e086ace613
commit b8bb77e20c
5 changed files with 106 additions and 36 deletions

View file

@ -1,11 +1,13 @@
import React, { useState, useCallback, useMemo, useRef } from 'react';
import React, { useState, useCallback, useMemo, useRef, useEffect } from 'react';
import Select from '@/_ui/Select';
import { components } from 'react-select';
import defaultStyles from '@/_ui/Select/styles';
import SolidIcon from '@/_ui/Icon/SolidIcons';
import { Checkbox } from '@/_ui/CheckBox/CheckBox';
import OverlayTrigger from 'react-bootstrap/OverlayTrigger';
import { isArray, isString } from 'lodash';
import { isArray } from 'lodash';
import useStore from '@/AppBuilder/_stores/store';
import { shallow } from 'zustand/shallow';
const { MenuList } = components;
@ -132,11 +134,32 @@ export const CustomSelectColumn = ({
optionsLoadingState = false,
horizontalAlignment = 'left',
isEditable,
column,
isNewRow,
}) => {
const validateWidget = useStore((state) => state.validateWidget, shallow);
const [isFocused, setIsFocused] = useState(false);
const containerRef = useRef(null);
const inputRef = useRef(null);
const validationData = validateWidget({
validationObject: {
customRule: { value: column.customRule },
},
widgetValue: value,
customResolveObjects: { value },
});
const { isValid, validationError } = validationData;
useEffect(() => {
const handleDocumentClick = (event) => {
if ((isMulti || isNewRow) && !containerRef.current?.contains(event.target)) setIsFocused(false);
};
document.addEventListener('mousedown', handleDocumentClick);
return () => document.removeEventListener('mousedown', handleDocumentClick);
}, [isMulti, isNewRow]);
const customComponents = {
MenuList: (props) => <CustomMenuList {...props} optionsLoadingState={optionsLoadingState} inputRef={inputRef} />,
Option: CustomOption,
@ -250,30 +273,52 @@ export const CustomSelectColumn = ({
trigger={isMulti && !isFocused && isOverflowing() && ['hover', 'focus']}
rootClose={true}
>
<div className="w-100 h-100 d-flex align-items-center" ref={containerRef}>
<Select
options={options}
hasSearch={false}
fuzzySearch={fuzzySearch}
isDisabled={disabled}
className={className}
components={customComponents}
value={selectedValue}
onMenuInputFocus={() => setIsFocused(true)}
onChange={handleChange}
useCustomStyles={true}
styles={customStyles}
defaultValue={defaultValue}
placeholder={placeholder}
isMulti={isMulti}
hideSelectedOptions={false}
isClearable={false}
clearIndicator={false}
darkMode={darkMode}
menuIsOpen={isFocused || undefined}
isFocused={isFocused || undefined}
/>
</div>
<>
<div
className="w-100 h-100 d-flex align-items-center"
ref={containerRef}
onClick={() => {
if (isNewRow && isEditable) {
setIsFocused((prev) => !prev);
}
}}
>
<Select
options={options}
hasSearch={false}
fuzzySearch={fuzzySearch}
isDisabled={disabled}
className={className}
components={customComponents}
value={selectedValue}
onMenuInputFocus={() => {
setIsFocused(true);
}}
onChange={handleChange}
useCustomStyles={true}
styles={customStyles}
defaultValue={defaultValue}
placeholder={placeholder}
isMulti={isMulti}
hideSelectedOptions={false}
isClearable={false}
clearIndicator={false}
darkMode={darkMode}
menuIsOpen={isFocused || undefined}
isFocused={isFocused || undefined}
/>
</div>
<div
onClick={() => {
if (!isValid) {
setIsFocused(true); // Open the dropdown
}
}}
className={` ${isValid ? 'd-none' : 'invalid-feedback d-block'}`}
>
{validationError}
</div>
</>
</OverlayTrigger>
);
};

View file

@ -70,6 +70,12 @@ export const StringColumn = ({
(ref?.current?.clientWidth < ref?.current?.children[0]?.offsetWidth ||
ref?.current?.clientHeight < ref?.current?.children[0]?.offsetHeight);
const focusInput = () => {
if (ref.current) {
ref.current.focus();
}
};
const renderEditableContent = () => (
<div className="h-100 d-flex flex-column justify-content-center position-relative">
<div
@ -106,11 +112,16 @@ export const StringColumn = ({
setIsEditing(true);
e.stopPropagation();
}}
suppressContentEditableWarning={true}
>
<HighLightSearch text={String(cellValue)} searchTerm={searchText} />
</div>
</div>
{!isValid && <div className="invalid-feedback text-truncate">{validationError}</div>}
{!isValid && (
<div className="invalid-feedback text-truncate" onClick={focusInput}>
{validationError}
</div>
)}
</div>
);

View file

@ -72,6 +72,12 @@ export const TextColumn = ({
[cellTextColor, isMaxRowHeightAuto, maxRowHeightValue, cellHeight]
);
const focusInput = () => {
if (cellRef.current) {
cellRef.current.focus();
}
};
const renderContent = useCallback(() => {
if (!isEditable) {
return (
@ -95,7 +101,7 @@ export const TextColumn = ({
darkMode ? 'textarea-dark-theme' : ''
}`}
style={{
...cellStyle,
color: cellTextColor || 'inherit',
maxWidth: containerWidth,
outline: 'none',
border: 'none',
@ -112,22 +118,25 @@ export const TextColumn = ({
handleContentChange(e.target.innerHTML);
}
}}
dangerouslySetInnerHTML={{ __html: DOMPurify.sanitize(cellValue) }}
onKeyDown={handleKeyDown}
onFocus={() => setIsEditing(true)}
/>
suppressContentEditableWarning={true}
>
<HighLightSearch text={String(cellValue)} searchTerm={searchText} />
</div>
);
}, [
isEditable,
isValid,
darkMode,
cellStyle,
cellTextColor,
containerWidth,
cellValue,
handleKeyDown,
handleContentChange,
horizontalAlignment,
cellValue,
searchText,
horizontalAlignment,
cellStyle,
handleContentChange,
]);
return (
@ -166,7 +175,11 @@ export const TextColumn = ({
>
{renderContent()}
</div>
{isEditable && !isValid && <div className="invalid-feedback text-truncate">{validationError}</div>}
{isEditable && !isValid && (
<div className="invalid-feedback text-truncate" onClick={focusInput}>
{validationError}
</div>
)}
</div>
</OverlayTrigger>
);

View file

@ -116,7 +116,6 @@ export const TableRow = ({
className={`td-container ${
cell.column.columnDef?.meta?.columnType === 'image' && 'jet-table-image-column h-100'
} ${cell.column.columnDef?.meta?.columnType !== 'image' && `w-100 h-100`}`}
style={{ display: 'flex', alignItems: 'center' }}
>
{flexRender(cell.column?.columnDef?.cell, cell.getContext())}
</div>

View file

@ -219,6 +219,8 @@ export default function generateColumnsData({
isEditable={isEditable}
isMulti={columnType === 'newMultiSelect'}
className="select-search table-select-search"
column={column}
isNewRow={columnForAddNewRow}
/>
);