I'm using react-datepicker and react-input-mask to create a controlled date input. I want to update the input border color dynamically:
Default state: Initial styles.
On focus: When the input is empty, the border should be purple.
The border should turn red if the input is invalid (e.g., incomplete date).
If valid: the Border should turn green.
<Controller
control={control}
name={name}
rules={{
validate: (value) => {
if (!value) return 'Date is required';
const cleanedValue = value.replace(/_/g, '').trim();
if (cleanedValue.length < 10) return 'Incomplete date';
const parsedDate = parse(cleanedValue, 'MM/dd/yyyy', new Date());
if (!isValid(parsedDate)) return 'Invalid date format';
return true;
},
}}
render={({ field, fieldState }) => {
const isInvalid =
fieldState.error ||
field.value.includes('_') ||
field.value.length < 10;
return (
<span
className={`input ${isInvalid ? 'error' : field.value ? 'valid' : ''}`}
style={{
borderColor: isInvalid
? 'red'
: field.value
? 'green'
: '#9095A1',
boxShadow: isInvalid
? '0 0 5px rgb(201,23,23)'
: field.value
? '0 0 5px rgb(40,224,24)'
: 'none',
}}
>
{IconLeft && <span className="icon">{IconLeft}</span>}
<DatePicker
disabled={disabled}
shouldCloseOnSelect={true}
placeholderText={placeholder}
selected={
field.value.length === 10
? parse(field.value, 'MM/dd/yyyy', new Date())
: null
}
minDate={minDate}
maxDate={maxDate}
onChange={(date) => {
const formattedDate = date ? format(date, 'MM/dd/yyyy') : '';
field.onChange(formattedDate);
}}
customInput={
<InputMask
mask="99/99/9999"
value={field.value || ''}
onChange={(e) => field.onChange(e.target.value)}
onFocus={(e) => {
e.target.style.borderColor = 'purple';
e.target.style.boxShadow = '0 0 5px purple';
}}
onBlur={(e) => {
if (
field.value.includes('_') ||
field.value.length < 10
) {
field.onChange('');
}
e.target.style.borderColor = isInvalid
? 'red'
: field.value
? 'green'
: 'initial';
e.target.style.boxShadow = isInvalid
? '0 0 5px rgb(201,23,23)'
: field.value
? '0 0 5px rgb(40,224,24)'
: 'none';
}}
disabled={disabled}
/>
}
/>
{IconRight && <span className="icon">{IconRight}</span>}
</span>
);
}}
/>
Since no one answered my question, I found the solution myself and am sharing it with others. This is a helper function that should used in Controller to set dynamic classNames and do not forget to set rules={{requier: true}}
export const getDynamicValidationColors = (field: { value: any }): string => {
if (field.value?.length === 0) {
return 'validatedPurple';
} else if (field.value) {
return 'validatedGreen';
} else {
return 'validatedPurple';
}
};