Skip to content

Commit 893c47e

Browse files
committed
Change behaviour of form field touched attribute
1 parent 1e076d9 commit 893c47e

File tree

7 files changed

+52
-27
lines changed

7 files changed

+52
-27
lines changed

src/Form/Field.js

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,23 @@ import PropTypes from 'prop-types';
44
const propTypes = {
55
children: PropTypes.node.isRequired,
66
error: PropTypes.string,
7+
touched: PropTypes.bool,
78
info: PropTypes.string,
89
};
910

1011
const defaultProps = {
1112
error: null,
13+
touched: false,
1214
info: null,
1315
};
1416

15-
function Field({ children, error, info }) {
17+
function Field({
18+
children, error, touched, info,
19+
}) {
1620
return (
1721
<fieldset className="form-group">
1822
{children}
19-
{error && <div className="form-text text-danger">{error}</div>}
23+
{!touched && error && <div className="form-text text-danger">{error}</div>}
2024
{info && <div className="form-text text-muted">{info}</div>}
2125
</fieldset>
2226
);

src/Form/FormCheckbox.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,20 +31,22 @@ class FormCheckbox extends React.Component {
3131
'custom-control-sm': size === 'sm',
3232
});
3333
const inputClasses = cx('custom-control-input', {
34-
'is-invalid': form.errors[name],
34+
'is-invalid': !form.touched[name] && form.errors[name],
3535
});
3636

3737
return (
38-
<Field error={form.errors[name]} info={info}>
38+
<Field error={form.errors[name]} touched={form.touched[name]} info={info}>
3939
{legend && <legend className="form-group-legend">{legend}</legend>}
4040
<label className={classes} htmlFor={`${this.identifier}-${name}`}>
4141
<input
4242
type="checkbox"
4343
id={`${this.identifier}-${name}`}
4444
name={name}
4545
checked={field.value || false}
46-
onChange={field.onChange}
47-
onBlur={field.onBlur}
46+
onChange={(event) => {
47+
if (!form.touched[name]) form.setFieldTouched(name, true);
48+
field.onChange(event);
49+
}}
4850
className={inputClasses}
4951
/>
5052
<div className="custom-control-indicator" />

src/Form/FormChoice.js

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,11 @@ class FormChoice extends React.Component {
4343
'custom-control-sm': size === 'sm',
4444
});
4545
const inputClasses = cx('custom-control-input', {
46-
'is-invalid': form.errors[name],
46+
'is-invalid': !form.touched[name] && form.errors[name],
4747
});
4848

4949
return (
50-
<Field error={form.errors[name]} info={info}>
50+
<Field error={form.errors[name]} touched={form.touched[name]} info={info}>
5151
{legend && <legend className="form-group-legend">{legend}</legend>}
5252
<div className="custom-controls-stacked">
5353
{options.map(option => (
@@ -64,10 +64,11 @@ class FormChoice extends React.Component {
6464
value={option.value}
6565
checked={field.value === option.value}
6666
onChange={(event) => {
67+
if (!form.touched[name]) form.setFieldTouched(name, true);
68+
6769
const value = event.target.checked ? option.value : field.value;
68-
return form.setFieldValue(name, value);
70+
form.setFieldValue(name, value);
6971
}}
70-
onBlur={() => form.setFieldTouched(name, true)}
7172
className={inputClasses}
7273
/>
7374
)}
@@ -79,16 +80,17 @@ class FormChoice extends React.Component {
7980
value={option.value}
8081
checked={field.value ? field.value.indexOf(option.value) !== -1 : false}
8182
onChange={(event) => {
83+
if (!form.touched[name]) form.setFieldTouched(name, true);
84+
8285
const newValue = field.value ? [...field.value] : [];
8386
if (event.target.checked) {
8487
newValue.push(option.value);
8588
} else {
8689
newValue.splice(newValue.indexOf(option.value), 1);
8790
}
8891

89-
return form.setFieldValue(name, newValue);
92+
form.setFieldValue(name, newValue);
9093
}}
91-
onBlur={() => form.setFieldTouched(`${name}[${getIndex()}]`, true)}
9294
className={inputClasses}
9395
/>
9496
)}

src/Form/FormDatePicker.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,11 @@ class FormDatePicker extends React.Component {
9595
// close dropdown
9696
this.updateState(false);
9797

98+
// touched
99+
if (!this.props.form.touched[this.props.field.name]) {
100+
this.props.form.setFieldTouched(this.props.field.name, true);
101+
}
102+
98103
// set value
99104
this.props.form.setFieldValue(this.props.field.name, day);
100105
};
@@ -130,7 +135,7 @@ class FormDatePicker extends React.Component {
130135
} = this.props;
131136

132137
const classes = cx('form-datepicker Select Select--single', {
133-
'is-invalid': form.errors[name],
138+
'is-invalid': !form.touched[name] && form.errors[name],
134139
'form-datepicker-sm': size === 'sm',
135140
'has-value': field.value,
136141
'is-focused': this.state.isFocused,
@@ -143,7 +148,7 @@ class FormDatePicker extends React.Component {
143148
const initialMonth = new Date(pickedDate.getFullYear(), pickedDate.getMonth());
144149

145150
return (
146-
<Field error={form.errors[name]} info={info}>
151+
<Field error={form.errors[name]} touched={form.touched[name]} info={info}>
147152
{label && (
148153
<label htmlFor={`${this.identifier}-${name}`} className="form-control-label">
149154
{label}
@@ -189,7 +194,6 @@ class FormDatePicker extends React.Component {
189194
onFocus={() => {
190195
this.updateState(undefined, true);
191196
}}
192-
onBlur={() => form.setFieldTouched(name, true)}
193197
style={{ border: '0px', width: '1px', display: 'inline-block' }}
194198
/>
195199
</span>

src/Form/FormInput.js

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ class FormInput extends React.Component {
4444
} = this.props;
4545

4646
const inputClasses = cx('form-control', {
47-
'is-invalid': form.errors[name],
47+
'is-invalid': !form.touched[name] && form.errors[name],
4848
'form-control-sm': size === 'sm',
4949
});
5050

5151
/* eslint-disable jsx-a11y/no-autofocus */
5252
return (
53-
<Field error={form.errors[name]} info={info}>
53+
<Field error={form.errors[name]} touched={form.touched[name]} info={info}>
5454
{label && (
5555
<label htmlFor={`${this.identifier}-${name}`} className="form-control-label">
5656
{label}
@@ -62,8 +62,10 @@ class FormInput extends React.Component {
6262
id={`${this.identifier}-${name}`}
6363
name={name}
6464
value={field.value || ''}
65-
onChange={field.onChange}
66-
onBlur={field.onBlur}
65+
onChange={(event) => {
66+
if (!form.touched[name]) form.setFieldTouched(name, true);
67+
field.onChange(event);
68+
}}
6769
placeholder={placeholder}
6870
className={inputClasses}
6971
autoFocus={autoFocus}
@@ -74,8 +76,10 @@ class FormInput extends React.Component {
7476
id={`${this.identifier}-${name}`}
7577
name={name}
7678
value={field.value || ''}
77-
onChange={field.onChange}
78-
onBlur={field.onBlur}
79+
onChange={(event) => {
80+
if (!form.touched[name]) form.setFieldTouched(name, true);
81+
field.onChange(event);
82+
}}
7983
placeholder={placeholder}
8084
rows="7"
8185
className={inputClasses}

src/Form/FormPicker.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -44,12 +44,12 @@ class FormPicker extends React.Component {
4444
} = this.props;
4545

4646
const classes = cx('form-picker', {
47-
'is-invalid': form.errors[name],
47+
'is-invalid': !form.touched[name] && form.errors[name],
4848
'form-picker-sm': size === 'sm',
4949
});
5050

5151
return (
52-
<Field error={form.errors[name]} info={info}>
52+
<Field error={form.errors[name]} touched={form.touched[name]} info={info}>
5353
{label && (
5454
<label htmlFor={`${this.identifier}-${name}`} className="form-control-label">
5555
{label}
@@ -62,6 +62,8 @@ class FormPicker extends React.Component {
6262
options={options}
6363
value={field.value}
6464
onChange={(value) => {
65+
if (!form.touched[name]) form.setFieldTouched(name, true);
66+
6567
// split value if multiple is enabled to get an array of values
6668
if (multiple) {
6769
form.setFieldValue(name, value.split(','));
@@ -70,7 +72,6 @@ class FormPicker extends React.Component {
7072

7173
form.setFieldValue(name, value);
7274
}}
73-
onBlur={() => form.setFieldTouched(name, true)}
7475
multi={multiple}
7576
clearable={clearable}
7677
searchable={searchable}

src/Form/FormSelect.js

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,22 @@ function FormSelect({
2323
children, legend, size, info, field: { name, ...field }, form,
2424
}) {
2525
const selectClasses = cx('custom-select', {
26-
'is-invalid': form.errors[name],
26+
'is-invalid': !form.touched[name] && form.errors[name],
2727
'custom-control-sm': size === 'sm',
2828
});
2929

3030
return (
31-
<Field error={form.errors[name]} info={info}>
31+
<Field error={form.errors[name]} touched={form.touched[name]} info={info}>
3232
{legend && <legend className="form-group-legend">{legend}</legend>}
33-
<select name={name} className={selectClasses} {...field}>
33+
<select
34+
name={name}
35+
value={field.value}
36+
onChange={(event) => {
37+
if (!form.touched[name]) form.setFieldTouched(name, true);
38+
field.onChange(event);
39+
}}
40+
className={selectClasses}
41+
>
3442
{children}
3543
</select>
3644
</Field>

0 commit comments

Comments
 (0)