Skip to content

Commit 3c7f62a

Browse files
authored
ChipsInput - fix validation (#3094)
* ChipsInput - fix validation * Fix required and call ref.validate on change * Take validateOnChange into account * Handle custom validation * Add validation to the screen
1 parent d21a65f commit 3c7f62a

File tree

2 files changed

+38
-1
lines changed

2 files changed

+38
-1
lines changed

demo/src/screens/componentScreens/ChipsInputScreen.tsx

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,10 @@ export default class ChipsInputScreen extends Component {
4545

4646
this.setState({chips: newChips});
4747
}}
48+
validate={'required'}
49+
validateOnChange
50+
validationMessage={'You must add at least one chip'}
51+
marginB-10
4852
/>
4953

5054
<ChipsInput

src/components/chipsInput/index.tsx

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import React, {useCallback, useMemo, useRef, useState, forwardRef} from 'react';
22
import {StyleSheet, NativeSyntheticEvent, TextInputKeyPressEventData} from 'react-native';
33
import {isUndefined, map} from 'lodash';
44
import {Constants} from '../../commons/new';
5-
import {useCombinedRefs} from '../../hooks';
5+
import {useCombinedRefs, useDidUpdate} from '../../hooks';
66
import TextField, {TextFieldProps} from '../textField';
77
import Chip, {ChipProps} from '../chip';
88

@@ -50,6 +50,7 @@ const ChipsInput = forwardRef((props: ChipsInputProps, refToForward: React.Ref<a
5050
onChange,
5151
fieldStyle,
5252
maxChips,
53+
validate,
5354
...others
5455
} = props;
5556
const [markedForRemoval, setMarkedForRemoval] = useState<number | undefined>(undefined);
@@ -146,6 +147,37 @@ const ChipsInput = forwardRef((props: ChipsInputProps, refToForward: React.Ref<a
146147
);
147148
}, [chips, leadingAccessory, defaultChipProps, removeMarkedChip, markedForRemoval, maxChips]);
148149

150+
const isRequired = useMemo(() => {
151+
if (!validate) {
152+
return false;
153+
}
154+
155+
const inputValidators = Array.isArray(validate) ? validate : [validate];
156+
return inputValidators.includes('required');
157+
}, [validate]);
158+
159+
const requiredValidator = useCallback(() => {
160+
return !isRequired || (chips?.length ?? 0) > 0;
161+
}, [isRequired, chips]);
162+
163+
const _validate = useMemo(() => {
164+
if (!validate) {
165+
return undefined;
166+
} else if (isRequired) {
167+
const inputValidators = Array.isArray(validate) ? validate : [validate];
168+
return inputValidators.map(validator => (validator === 'required' ? requiredValidator : validator));
169+
} else {
170+
return validate;
171+
}
172+
}, [validate, isRequired, requiredValidator]);
173+
174+
useDidUpdate(() => {
175+
if (others.validateOnChange) {
176+
// @ts-expect-error
177+
fieldRef.current?.validate();
178+
}
179+
}, [chips, others.validateOnChange]);
180+
149181
return (
150182
<TextField
151183
// @ts-expect-error
@@ -159,6 +191,7 @@ const ChipsInput = forwardRef((props: ChipsInputProps, refToForward: React.Ref<a
159191
fieldStyle={[fieldStyle, styles.fieldStyle]}
160192
onKeyPress={onKeyPress}
161193
accessibilityHint={props.editable ? 'press keyboard delete button to remove last tag' : undefined}
194+
validate={_validate}
162195
/>
163196
);
164197
});

0 commit comments

Comments
 (0)