Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: validate onBlur #78

Merged
merged 1 commit into from
Aug 28, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion src/components/Checkbox/Checkbox.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,10 @@ function Checkbox({
<MuiCheckbox
data-testid={`option-${index}`}
checked={field.value.includes(option.value)}
onChange={e => handleChecked(e, options, option, field, form.setFieldValue)}
onChange={e => {
handleChecked(e, options, option, field, form.setFieldValue);
form.setFieldTouched(field.name, false);
}}
/>
)}
label={option.label}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Checkbox/Checkbox.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('<Checkbox>', () => {
],
label: {text: 'Select the options'},
field: {value: [], name: 'test'},
form: {setFieldValue: jest.fn(), errors: {}, submitCount: 0},
form: {setFieldValue: jest.fn(), setFieldTouched: jest.fn(), errors: {}, submitCount: 0},
readOnlyMode: false,
required: true,
warnings: {}
Expand Down
2 changes: 1 addition & 1 deletion src/components/Currency/Currency.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ function Currency({form, field, label, ...props}) {
const handleChange = values => {
const {formattedValue} = values;
form.setFieldValue(field.name, formattedValue);
form.setFieldTouched(field.name, true);
form.setFieldTouched(field.name, false);
};

return (
Expand Down
10 changes: 8 additions & 2 deletions src/components/DatePicker/DatePicker.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ function DatePicker({
type={dateType}
label={isRange ? 'Fecha de inicio' : ''}
value={isRange ? field.value.start : field.value}
onChange={newValue => form.setFieldValue(isRange ? `${field.name}.start` : field.name, newValue)}
onChange={newValue => {
form.setFieldValue(isRange ? `${field.name}.start` : field.name, newValue);
form.setFieldTouched(isRange ? `${field.name}.start` : field.name, false);
}}
renderInput={params => (
<TextField
{...params}
Expand All @@ -46,7 +49,10 @@ function DatePicker({
type={dateType}
label="Fecha de fin"
value={field.value.end}
onChange={newValue => form.setFieldValue(`${field.name}.end`, newValue)}
onChange={newValue => {
form.setFieldValue(`${field.name}.end`, newValue);
form.setFieldTouched(`${field.name}.end`, false);
}}
renderInput={params => (
<TextField
{...params}
Expand Down
7 changes: 4 additions & 3 deletions src/components/FormBuilder/FormBuilder.js
Original file line number Diff line number Diff line change
Expand Up @@ -43,8 +43,9 @@ function FormBuilder({
enableReinitialize
validationSchema={validateSchema}
onSubmit={onSubmit}
validateOnChange={false}
>
{({values, setValues, errors}) => {
{({values, setValues}) => {
const warnings = getWarnings(warningSchema, values) || {};
return (
<Form>
Expand All @@ -64,7 +65,7 @@ function FormBuilder({
section={section}
values={currentSection}
isReadOnly={isReadOnly}
isValid={!errors?.[section.name]?.[index]}
isValid={validateSchema.isValidSync({[section.name]: values?.[section.name]})}
/>
) : (
<SectionHeader
Expand All @@ -75,7 +76,7 @@ function FormBuilder({
section={section}
values={currentSection}
isReadOnly={isReadOnly}
isValid={!errors?.[section.name]?.[index]}
isValid={validateSchema.isValidSync({[section.name]: values?.[section.name]})}
/>
)
}
Expand Down
4 changes: 2 additions & 2 deletions src/components/InputLabel/InputLabel.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import labelPropTypes from '@/utils/propTypes/label';
function InputLabel({
label, form, field, disabled, warnings
}) {
const {hasWarning, hasError, fieldMustBeCompleted} = hasFormikErrorsAndWarnings({form, field, warnings});
const {hasWarning, hasError} = hasFormikErrorsAndWarnings({form, field, warnings});
return (
<Stack direction="row" spacing={2} data-testid="input-label">
<Stack direction="row" mb={0.5} alignItems="center" sx={{opacity: !disabled ? 1 : 0.3}}>
Expand All @@ -38,7 +38,7 @@ function InputLabel({
<Typography sx={{fontWeight: 'bold', fontSize: '17px'}}>
{label.text}
{' '}
{fieldMustBeCompleted && '*'}
{hasError && '*'}
</Typography>
</Stack>
{hasError && !disabled && (
Expand Down
5 changes: 4 additions & 1 deletion src/components/Radio/MobileRadio/MobileRadio.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,10 @@ function MobileRadio({
disabled={disabled}
variant={option.value === field.value ? 'contained' : 'outlined'}
onClick={
() => form.setFieldValue(field.name, option.value === field.value ? '' : option.value)
() => {
form.setFieldValue(field.name, option.value === field.value ? '' : option.value);
form.setFieldTouched(field.name, false);
}
}
size="small"
>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Radio/MobileRadio/MobileRadio.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('<MobileRadio>', () => {
required: false,
label: 'Select an option',
field: {value: '', name: 'test'},
form: {setFieldValue: jest.fn(), errors: {}, submitCount: 0}
form: {setFieldValue: jest.fn(), setFieldTouched: jest.fn(), errors: {}, submitCount: 0}
};
});

Expand Down
13 changes: 10 additions & 3 deletions src/components/Radio/Radio.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import MuiRadio from '@mui/material/Radio';
import RadioGroup from '@mui/material/RadioGroup';
import FormControlLabel from '@mui/material/FormControlLabel';
import Stack from '@mui/material/Stack';
import ClearIcon from '@mui/icons-material/Clear';
import DeleteIcon from '@mui/icons-material/Delete';

import FieldMessage from '@/components/FieldMessage';
import InputLabel from '@/components/InputLabel';
Expand All @@ -31,7 +31,14 @@ function Radio({
) : (
<Stack direction="column" sx={{width: '100%'}} data-testid="radio">
<InputLabel warnings={warnings} form={form} field={field} label={label} disabled={disabled} />
<RadioGroup {...field}>
<RadioGroup
{...field}
onBlur={form.handleBlur}
onChange={e => {
field.onChange(e);
form.setFieldTouched(field.name, false);
}}
>
{options.map((option, index) => (
<Stack key={option.value} direction="row">
<FormControlLabel
Expand All @@ -48,7 +55,7 @@ function Radio({
color="error"
data-testid={`clean-option-${index}`}
>
<ClearIcon />
<DeleteIcon />
</IconButton>
)}
</Stack>
Expand Down
2 changes: 1 addition & 1 deletion src/components/Radio/Radio.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ describe('<Radio>', () => {
required: false,
label: 'Select an option',
field: {value: '', name: 'test'},
form: {setFieldValue: jest.fn(), errors: {}, submitCount: 0}
form: {setFieldValue: jest.fn(), setFieldTouched: jest.fn(), errors: {}, submitCount: 0}
};
});

Expand Down
5 changes: 4 additions & 1 deletion src/components/RadioTable/RadioTable.js
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,10 @@ function RadioTable({
<MuiRadio
checked={subOption.value === field.value[option.name]}
onChange={
e => form.setFieldValue(`${field.name}.${option.name}`, e.target.value)
e => {
form.setFieldValue(`${field.name}.${option.name}`, e.target.value);
form.setFieldTouched(field.name, false);
}
}
/>
)}
Expand Down
2 changes: 1 addition & 1 deletion src/components/RadioTable/RadioTable.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ describe('<RadioTable>', () => {
required: false,
label: 'Select the correct options',
field: {value: {S1P1O1: undefined, S1P1O2: undefined, S1P1O3: undefined}, name: 'test'},
form: {setFieldValue: jest.fn(), errors: {}, submitCount: 0}
form: {setFieldValue: jest.fn(), setFieldTouched: jest.fn(), errors: {}, submitCount: 0}
};
});

Expand Down
2 changes: 2 additions & 0 deletions src/components/Select/Select.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ function Select({
}) {
const handleChange = selectedValue => {
form.setFieldValue(field.name, selectedValue ? selectedValue[keyValue] : undefined);
form.setFieldTouched(field.name, false);
onClean(form);
};
const selectedValue = useMemo(() => options.find(option => option[keyValue] === field.value) || {}, [field?.value]);
Expand Down Expand Up @@ -39,6 +40,7 @@ function Select({
getOptionLabel={option => option.label || ''}
value={selectedValue}
disabled={disabled}
onBlur={form.handleBlur}
/>
);
}
Expand Down
5 changes: 5 additions & 0 deletions src/components/TextField/TextField.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,13 @@ function TextField({
)
}}
{...field}
onChange={e => {
field.onChange(e);
form.setFieldTouched(field.name, false);
}}
{...props}
disabled={disabled}
onBlur={form.handleBlur}
/>
<FieldMessage warnings={warnings} form={form} field={field} disabled={disabled} />
</Box>
Expand Down
2 changes: 1 addition & 1 deletion src/components/TextField/TextField.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ describe('<TextField>', () => {
label: {text: 'Write your name'},
disabled: false,
field: {value: '', name: 'test', onChange: jest.fn()},
form: {errors: {}, submitCount: 0},
form: {errors: {}, submitCount: 0, setFieldTouched: jest.fn()},
required: false
};
});
Expand Down
17 changes: 11 additions & 6 deletions src/utils/hasFormikErrorsAndWarnings.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,18 @@ const hasFormikErrorsAndWarnings = ({form, field, warnings = {}}) => {
const warning = getIn(warnings, field.name);
const error = getIn(form.errors, field.name);
const touched = getIn(form.touched, field.name);
const formSubmittedOrTouched = form.submitCount > 0 || touched;
const formSubmittedOrTouched = form.submitCount > 0 && touched;
if (formSubmittedOrTouched || (touched && (error || warning))) {
return {
hasError: !!error,
error,
hasWarning: !!warning,
warning
};
}
return {
fieldMustBeCompleted: !!error,
hasError: !!(formSubmittedOrTouched && error),
error,
hasWarning: !!(formSubmittedOrTouched && warning),
warning
hasError: false,
hasWarning: false
};
};

Expand Down