Merge pull request #11320 from ToolJet/fix-custom-validation-form-elements

Fix validate action not triggered when used with different components in custom validation
This commit is contained in:
Johnson Cherian 2024-11-14 11:39:28 +05:30 committed by GitHub
commit a8d9486f94
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 50 additions and 46 deletions

View file

@ -80,7 +80,7 @@ const RenderWidget = ({
...{ validationObject: unResolvedValidation },
customResolveObjects: customResolvables,
}),
[validateWidget, customResolvables, unResolvedValidation]
[validateWidget, customResolvables, unResolvedValidation, resolvedValidation]
);
const resetComponent = useCallback(() => {

View file

@ -149,7 +149,7 @@ export function generateUIComponents(JSONSchema, advanced, componentName = '') {
uiComponentsDraft[index * 2 + 1]['definition']['properties']['display_values'] = value?.displayValues;
if (value?.label) uiComponentsDraft[index * 2 + 1]['definition']['properties']['label'] = value?.label;
if (value?.value) uiComponentsDraft[index * 2 + 1]['definition']['properties']['value'] = value?.value;
if (value?.values) uiComponentsDraft[index * 2 + 1]['definition']['properties']['value'] = value?.values;
if (value?.values) uiComponentsDraft[index * 2 + 1]['definition']['properties']['values'] = value?.values;
if (value?.loading)
uiComponentsDraft[index * 2 + 1]['definition']['properties']['loadingState'] = value?.loading;
break;
@ -363,7 +363,7 @@ export function generateUIComponents(JSONSchema, advanced, componentName = '') {
uiComponentsDraft[index * 2 + 1]['definition']['properties']['display_values'] = value?.displayValues;
if (value?.label) uiComponentsDraft[index * 2 + 1]['definition']['properties']['label'] = value?.label;
if (value?.value) uiComponentsDraft[index * 2 + 1]['definition']['properties']['value'] = value?.value;
if (value?.values) uiComponentsDraft[index * 2 + 1]['definition']['properties']['value'] = value?.values;
if (value?.values) uiComponentsDraft[index * 2 + 1]['definition']['properties']['values'] = value?.values;
if (value?.showAllOption)
uiComponentsDraft[index * 2 + 1]['definition']['properties']['showAllOption'] = value?.showAllOption;
break;

View file

@ -253,7 +253,7 @@ export const Checkbox = ({
</>
)}
</div>
{validationError && visibility && !checked && userInteracted && (
{!isValid && visibility && userInteracted && (
<div
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
style={{

View file

@ -101,6 +101,8 @@ export const DropdownV2 = ({
const [isDropdownDisabled, setIsDropdownDisabled] = useState(disabledState);
const [searchInputValue, setSearchInputValue] = useState('');
const [isDropdownOpen, setIsDropdownOpen] = useState(false);
const [userInteracted, setUserInteracted] = useState(false);
const _height = padding === 'default' ? `${height}px` : `${height + 4}px`;
const labelRef = useRef();
function findDefaultItem(schema) {
@ -317,6 +319,7 @@ export const DropdownV2 = ({
accentColor,
isLoading: isDropdownLoading,
isDisabled: isDropdownDisabled,
userInteracted,
}),
backgroundColor: getInputBackgroundColor({
fieldBackgroundColor,
@ -479,6 +482,7 @@ export const DropdownV2 = ({
fireEvent('onSelect');
}
setIsDropdownOpen(false);
setUserInteracted(true);
}}
options={selectOptions}
styles={customStyles}
@ -507,19 +511,20 @@ export const DropdownV2 = ({
/>
</div>
</div>
<div
className={`${isValid ? '' : visibility ? 'd-flex' : 'none'}`}
style={{
color: errTextColor,
justifyContent: direction === 'right' ? 'flex-start' : 'flex-end',
fontSize: '11px',
fontWeight: '400',
lineHeight: '16px',
display: visibility ? 'block' : 'none',
}}
>
{!isValid && validationError}
</div>
{userInteracted && visibility && !isValid && (
<div
className={'d-flex'}
style={{
color: errTextColor,
justifyContent: direction === 'right' ? 'flex-start' : 'flex-end',
fontSize: '11px',
fontWeight: '400',
lineHeight: '16px',
}}
>
{validationError}
</div>
)}
</>
);
};

View file

@ -7,8 +7,16 @@ export const getInputFocusedColor = ({ accentColor }) => {
return 'var(--primary-accent-strong)';
};
export const getInputBorderColor = ({ isValid, isFocused, fieldBorderColor, accentColor, isLoading, isDisabled }) => {
if (!isValid) {
export const getInputBorderColor = ({
isValid,
isFocused,
fieldBorderColor,
accentColor,
isLoading,
isDisabled,
userInteracted,
}) => {
if (userInteracted && !isValid) {
return 'var(--status-error-strong)';
}

View file

@ -12,8 +12,6 @@ import Label from '@/_ui/Label';
const tinycolor = require('tinycolor2');
import { CustomDropdownIndicator, CustomClearIndicator } from '../DropdownV2/DropdownV2';
import { getInputBackgroundColor, getInputBorderColor, getInputFocusedColor } from '../DropdownV2/utils';
import useStore from '@/AppBuilder/_stores/store';
import { shallow } from 'zustand/shallow';
export const MultiselectV2 = ({
id,
@ -28,7 +26,6 @@ export const MultiselectV2 = ({
validate,
validation,
componentName,
width,
}) => {
let {
label,
@ -76,6 +73,7 @@ export const MultiselectV2 = ({
const [isSelectAllSelected, setIsSelectAllSelected] = useState(false);
const [searchInputValue, setSearchInputValue] = useState('');
const _height = padding === 'default' ? `${height}px` : `${height + 4}px`;
const [userInteracted, setUserInteracted] = useState(false);
const [isMultiselectOpen, setIsMultiselectOpen] = useState(false);
useEffect(() => {
@ -129,9 +127,7 @@ export const MultiselectV2 = ({
const onChangeHandler = (items, action) => {
setInputValue(items);
fireEvent('onSelect');
// if (action.action === 'select-option') {
// fireEvent('onSelect');
// }
setUserInteracted(true);
};
useEffect(() => {
@ -332,6 +328,7 @@ export const MultiselectV2 = ({
accentColor,
isLoading: isMultiSelectLoading,
isDisabled: isMultiSelectDisabled,
userInteracted,
}),
backgroundColor: getInputBackgroundColor({
fieldBackgroundColor,
@ -420,7 +417,6 @@ export const MultiselectV2 = ({
}),
};
const _width = (labelWidth / 100) * 70; // Max width which label can go is 70% for better UX calculate width based on this value
return (
<>
<div
@ -520,19 +516,20 @@ export const MultiselectV2 = ({
/>
</div>
</div>
<div
className={`${isValid ? '' : visibility ? 'd-flex' : 'none'}`}
style={{
color: errTextColor,
justifyContent: direction === 'right' ? 'flex-start' : 'flex-end',
fontSize: '11px',
fontWeight: '400',
lineHeight: '16px',
display: visibility ? 'block' : 'none',
}}
>
{!isValid && validationError}
</div>
{userInteracted && visibility && !isValid && (
<div
className={'d-flex'}
style={{
color: errTextColor,
justifyContent: direction === 'right' ? 'flex-start' : 'flex-end',
fontSize: '11px',
fontWeight: '400',
lineHeight: '16px',
}}
>
{validationError}
</div>
)}
</>
);
};

View file

@ -12,7 +12,6 @@ const Switch = ({
borderColor,
setOn,
styles,
setExposedVariable,
fireEvent,
setUserInteracted,
}) => {
@ -106,7 +105,6 @@ export const ToggleSwitchV2 = ({
const isMandatory = validation?.mandatory ?? false;
const [validationStatus, setValidationStatus] = useState(validate(on));
const { isValid, validationError } = validationStatus;
const [showValidationError, setShowValidationError] = useState(true);
const [loading, setLoading] = useState(properties?.loadingState);
const [disable, setDisable] = useState(properties.disabledState || properties.loadingState);
const [visibility, setVisibility] = useState(properties.visibility);
@ -276,15 +274,11 @@ export const ToggleSwitchV2 = ({
onChange={toggleValue}
color={toggleSwitchColor}
alignment={alignment}
validationError={validationError}
isValid={isValid}
showValidationError={showValidationError}
properties={properties}
setShowValidationError={setShowValidationError}
borderColor={borderColor}
setOn={setInputValue}
styles={styles}
setExposedVariable={setExposedVariable}
fireEvent={fireEvent}
setUserInteracted={setUserInteracted}
/>
@ -300,7 +294,7 @@ export const ToggleSwitchV2 = ({
}}
>
{renderInput()}
{showValidationError && isMandatory && userInteracted && !on && visibility && (
{userInteracted && visibility && !isValid && (
<div
data-cy={`${String(componentName).toLowerCase()}-invalid-feedback`}
style={{