Skip to content

Commit fc65543

Browse files
authored
🐛 Update validation method for forms to validate onBlur & onChange (#1310)
Resolves https://issues.redhat.com/browse/MTA-1196 Signed-off-by: ibolton336 <[email protected]>
1 parent c763fc3 commit fc65543

File tree

24 files changed

+41
-39
lines changed

24 files changed

+41
-39
lines changed

client/src/app/components/HookFormPFFields/HookFormPFGroupController.tsx

+3-2
Original file line numberDiff line numberDiff line change
@@ -59,8 +59,9 @@ export const HookFormPFGroupController = <
5959
control={control}
6060
name={name}
6161
render={({ field, fieldState, formState }) => {
62-
const { isDirty, error } = fieldState;
63-
const shouldDisplayError = error?.message && isDirty && !errorsSuppressed;
62+
const { isDirty, isTouched, error } = fieldState;
63+
const shouldDisplayError =
64+
error?.message && (isDirty || isTouched) && !errorsSuppressed;
6465
return (
6566
<FormGroup
6667
labelIcon={labelIcon}

client/src/app/components/HookFormPFFields/HookFormPFTextArea.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ export const HookFormPFTextArea = <
3030
{...extractedProps}
3131
renderInput={({
3232
field: { onChange, onBlur, value, name, ref },
33-
fieldState: { isDirty, error },
33+
fieldState: { isDirty, error, isTouched },
3434
}) => (
3535
<TextArea
3636
ref={ref}
@@ -44,7 +44,7 @@ export const HookFormPFTextArea = <
4444
validated={
4545
errorsSuppressed
4646
? "default"
47-
: getValidatedFromErrors(error, isDirty)
47+
: getValidatedFromErrors(error, isDirty, isTouched)
4848
}
4949
{...remainingProps}
5050
/>

client/src/app/components/HookFormPFFields/HookFormPFTextInput.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ export const HookFormPFTextInput = <
3131
{...extractedProps}
3232
renderInput={({
3333
field: { onChange, onBlur, value, name, ref },
34-
fieldState: { isDirty, error },
34+
fieldState: { isDirty, error, isTouched },
3535
}) => (
3636
<TextInput
3737
ref={ref}
@@ -56,7 +56,7 @@ export const HookFormPFTextInput = <
5656
validated={
5757
errorsSuppressed
5858
? "default"
59-
: getValidatedFromErrors(error, isDirty)
59+
: getValidatedFromErrors(error, isDirty, isTouched)
6060
}
6161
{...remainingProps}
6262
/>

client/src/app/components/StringListField.tsx

+2-2
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export const StringListField: React.FC<StringListFieldProps> = ({
6262
label={itemToAddLabel}
6363
renderInput={({
6464
field: { onChange, onBlur, value, ref },
65-
fieldState: { isDirty, error },
65+
fieldState: { isDirty, error, isTouched },
6666
}) => {
6767
const isValid = !!value && !error;
6868
const addItem = () => {
@@ -75,7 +75,7 @@ export const StringListField: React.FC<StringListFieldProps> = ({
7575
ref={ref}
7676
id={itemToAddFieldId}
7777
aria-label={itemToAddAriaLabel}
78-
validated={getValidatedFromErrors(error, isDirty)}
78+
validated={getValidatedFromErrors(error, isDirty, isTouched)}
7979
value={value}
8080
onChange={(_, value) => onChange(value)}
8181
onBlur={onBlur}

client/src/app/pages/applications/analysis-wizard/analysis-wizard.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ export const AnalysisWizard: React.FC<IAnalysisWizard> = ({
175175
autoTaggingEnabled: true,
176176
},
177177
resolver: yupResolver(allFieldsSchema),
178-
mode: "onChange",
178+
mode: "all",
179179
});
180180

181181
const { handleSubmit, watch, reset } = methods;

client/src/app/pages/applications/analysis-wizard/set-options.tsx

+4-4
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ export const SetOptions: React.FC = () => {
8888
fieldId="target-labels"
8989
renderInput={({
9090
field: { onChange, onBlur },
91-
fieldState: { isDirty, error },
91+
fieldState: { isDirty, error, isTouched },
9292
}) => {
9393
const targetSelections = formLabels
9494
.map((formLabel) => {
@@ -139,7 +139,7 @@ export const SetOptions: React.FC = () => {
139139
onClear={() => {
140140
onChange([]);
141141
}}
142-
validated={getValidatedFromErrors(error, isDirty)}
142+
validated={getValidatedFromErrors(error, isDirty, isTouched)}
143143
>
144144
{defaultTargetsAndTargetsLabels.map((targetLabel, index) => (
145145
<SelectOption
@@ -159,7 +159,7 @@ export const SetOptions: React.FC = () => {
159159
fieldId="sources"
160160
renderInput={({
161161
field: { onChange, onBlur, value },
162-
fieldState: { isDirty, error },
162+
fieldState: { isDirty, error, isTouched },
163163
}) => {
164164
const sourceSelections = formLabels
165165
.map((formLabel) => {
@@ -211,7 +211,7 @@ export const SetOptions: React.FC = () => {
211211
onClear={() => {
212212
onChange([]);
213213
}}
214-
validated={getValidatedFromErrors(error, isDirty)}
214+
validated={getValidatedFromErrors(error, isDirty, isTouched)}
215215
>
216216
{defaultSourcesAndSourcesLabels.map((targetLabel, index) => (
217217
<SelectOption

client/src/app/pages/applications/application-assessment/components/application-assessment-wizard/application-assessment-wizard.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ export const ApplicationAssessmentWizard: React.FC<
115115
[SAVE_ACTION_KEY]: SAVE_ACTION_VALUE.SAVE_AS_DRAFT,
116116
};
117117
}, [assessment]),
118-
mode: "onChange",
118+
mode: "all",
119119
});
120120
const values = methods.getValues();
121121

client/src/app/pages/applications/application-review/components/review-form/review-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export const ReviewForm: React.FC<IReviewFormProps> = ({
9898
comments: review?.comments || "",
9999
},
100100
resolver: yupResolver(validationSchema),
101-
mode: "onChange",
101+
mode: "all",
102102
});
103103

104104
const onInvalid = (errors: FieldErrors<FormValues>) => {

client/src/app/pages/applications/components/application-form/application-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -255,7 +255,7 @@ export const ApplicationForm: React.FC<ApplicationFormProps> = ({
255255
packaging: getBinaryInitialValue(application, "packaging"),
256256
},
257257
resolver: yupResolver(validationSchema),
258-
mode: "onChange",
258+
mode: "all",
259259
});
260260

261261
const buildBinaryFieldString = (

client/src/app/pages/applications/components/application-identity-form/application-identity-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -159,7 +159,7 @@ export const ApplicationIdentityForm: React.FC<
159159
resolver: yupResolver(
160160
validationSchema({ [SOURCE_CREDENTIALS]: false, [MAVEN_SETTINGS]: false })
161161
),
162-
mode: "onChange",
162+
mode: "all",
163163
});
164164

165165
useEffect(() => {

client/src/app/pages/controls/business-services/components/business-service-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,7 @@ export const BusinessServiceForm: React.FC<BusinessServiceFormProps> = ({
8989
owner: businessService?.owner?.name,
9090
},
9191
resolver: yupResolver(validationSchema),
92-
mode: "onChange",
92+
mode: "all",
9393
});
9494

9595
const onCreateBusinessServiceSuccess = (

client/src/app/pages/controls/job-functions/components/job-function-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ export const JobFunctionForm: React.FC<JobFunctionFormProps> = ({
6767
name: jobFunction?.name || "",
6868
},
6969
resolver: yupResolver(validationSchema),
70-
mode: "onChange",
70+
mode: "all",
7171
});
7272

7373
const onCreateJobFunctionSuccess = (response: AxiosResponse<JobFunction>) => {

client/src/app/pages/controls/stakeholder-groups/components/stakeholder-group-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ export const StakeholderGroupForm: React.FC<StakeholderGroupFormProps> = ({
106106
),
107107
},
108108
resolver: yupResolver(validationSchema),
109-
mode: "onChange",
109+
mode: "all",
110110
});
111111

112112
const onCreateStakeholderGroupSuccess = (

client/src/app/pages/controls/stakeholders/components/stakeholder-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ export const StakeholderForm: React.FC<StakeholderFormProps> = ({
111111
),
112112
},
113113
resolver: yupResolver(validationSchema),
114-
mode: "onChange",
114+
mode: "all",
115115
});
116116

117117
const onCreateStakeholderSuccess = (_: AxiosResponse<Stakeholder>) =>

client/src/app/pages/controls/tags/components/tag-category-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export const TagCategoryForm: React.FC<TagCategoryFormProps> = ({
9292
: null,
9393
},
9494
resolver: yupResolver(validationSchema),
95-
mode: "onChange",
95+
mode: "all",
9696
});
9797

9898
const onTagSuccess = (_: AxiosResponse<TagCategory>) =>

client/src/app/pages/controls/tags/components/tag-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ export const TagForm: React.FC<TagFormProps> = ({ tag, onClose }) => {
8686
tagCategory: tagCategoryInitialValue?.name,
8787
},
8888
resolver: yupResolver(validationSchema),
89-
mode: "onChange",
89+
mode: "all",
9090
});
9191

9292
const onTagSuccess = (_: AxiosResponse<Tag>) =>

client/src/app/pages/external/jira/tracker-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -176,7 +176,7 @@ export const TrackerForm: React.FC<TrackerFormProps> = ({
176176
insecure: tracker?.insecure || false,
177177
},
178178
resolver: yupResolver(validationSchema),
179-
mode: "onChange",
179+
mode: "all",
180180
});
181181

182182
const values = getValues();

client/src/app/pages/identities/components/identity-form/identity-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -392,7 +392,7 @@ export const IdentityForm: React.FC<IdentityFormProps> = ({
392392
user: identity?.user || "",
393393
},
394394
resolver: yupResolver(validationSchema),
395-
mode: "onChange",
395+
mode: "all",
396396
});
397397

398398
const values = getValues();

client/src/app/pages/migration-targets/components/custom-target-form.tsx

+1-3
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ export const CustomTargetForm: React.FC<CustomTargetFormProps> = ({
184184
rootPath: target?.ruleset?.repository?.path,
185185
},
186186
resolver: yupResolver(validationSchema),
187-
mode: "onChange",
187+
mode: "all",
188188
});
189189

190190
const {
@@ -308,7 +308,6 @@ export const CustomTargetForm: React.FC<CustomTargetFormProps> = ({
308308
return handleFileUpload(defaultImageFile);
309309
})
310310
.then((res) => {
311-
console.log("res ", res);
312311
updateTarget({
313312
...payload,
314313
image: { id: res.id },
@@ -329,7 +328,6 @@ export const CustomTargetForm: React.FC<CustomTargetFormProps> = ({
329328
return handleFileUpload(defaultImageFile);
330329
})
331330
.then((res) => {
332-
console.log("res ", res);
333331
createTarget({
334332
...payload,
335333
image: { id: res.id },

client/src/app/pages/migration-waves/components/export-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ export const ExportForm: React.FC<ExportFormProps> = ({
9292
kind: "",
9393
},
9494
resolver: yupResolver(validationSchema),
95-
mode: "onChange",
95+
mode: "all",
9696
});
9797

9898
const values = watch();

client/src/app/pages/migration-waves/components/migration-wave-form.tsx

+1-1
Original file line numberDiff line numberDiff line change
@@ -211,7 +211,7 @@ export const WaveForm: React.FC<WaveFormProps> = ({
211211
watch,
212212
trigger,
213213
} = useForm<WaveFormValues>({
214-
mode: "onChange",
214+
mode: "all",
215215
defaultValues: {
216216
name: migrationWave?.name || "",
217217
startDateStr: migrationWave?.startDate

client/src/app/pages/proxies/proxy-form.tsx

+5-5
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ export const ProxyForm: React.FC<ProxyFormProps> = ({
9595
[httpProxy, httpsProxy]
9696
),
9797
resolver: yupResolver(useProxyFormValidationSchema()),
98-
mode: "onChange",
98+
mode: "all",
9999
});
100100

101101
const values = getValues();
@@ -271,7 +271,7 @@ export const ProxyForm: React.FC<ProxyFormProps> = ({
271271
isRequired
272272
renderInput={({
273273
field: { onChange, value },
274-
fieldState: { isDirty, error },
274+
fieldState: { isDirty, error, isTouched },
275275
}) => (
276276
<SimpleSelect
277277
id="httpIdentity"
@@ -284,7 +284,7 @@ export const ProxyForm: React.FC<ProxyFormProps> = ({
284284
const selectionValue = selection as OptionWithValue<string>;
285285
onChange(selectionValue.value);
286286
}}
287-
validated={getValidatedFromErrors(error, isDirty)}
287+
validated={getValidatedFromErrors(error, isDirty, isTouched)}
288288
/>
289289
)}
290290
/>
@@ -357,7 +357,7 @@ export const ProxyForm: React.FC<ProxyFormProps> = ({
357357
className={spacing.mMd}
358358
renderInput={({
359359
field: { onChange, value },
360-
fieldState: { isDirty, error },
360+
fieldState: { isDirty, error, isTouched },
361361
}) => (
362362
<SimpleSelect
363363
toggleId="https-proxy-credentials-select-toggle"
@@ -369,7 +369,7 @@ export const ProxyForm: React.FC<ProxyFormProps> = ({
369369
const selectionValue = selection as OptionWithValue<string>;
370370
onChange(selectionValue.value);
371371
}}
372-
validated={getValidatedFromErrors(error, isDirty)}
372+
validated={getValidatedFromErrors(error, isDirty, isTouched)}
373373
/>
374374
)}
375375
/>

client/src/app/utils/utils.test.ts

+4-2
Original file line numberDiff line numberDiff line change
@@ -70,16 +70,18 @@ describe("utils", () => {
7070
it("getValidatedFromErrors: given 'error' and 'touched' return 'error'", () => {
7171
const error = "Any value";
7272
const dirty = true;
73+
const isTouched = true;
7374

74-
const status = getValidatedFromErrors(error, dirty);
75+
const status = getValidatedFromErrors(error, dirty, isTouched);
7576
expect(status).toBe("error");
7677
});
7778

7879
it("getValidatedFromErrors: given 'error' but not 'touched' return 'default'", () => {
7980
const error = "Any value";
8081
const dirty = false;
82+
const isTouched = false;
8183

82-
const status = getValidatedFromErrors(error, dirty);
84+
const status = getValidatedFromErrors(error, dirty, isTouched);
8385
expect(status).toBe("default");
8486
});
8587

client/src/app/utils/utils.ts

+3-2
Original file line numberDiff line numberDiff line change
@@ -92,9 +92,10 @@ export const objectKeys = <T extends Object>(obj: T) =>
9292

9393
export const getValidatedFromErrors = (
9494
error: unknown | undefined,
95-
dirty: boolean | undefined
95+
dirty: boolean | undefined,
96+
isTouched: boolean | undefined
9697
) => {
97-
return error && dirty ? "error" : "default";
98+
return error && (dirty || isTouched) ? "error" : "default";
9899
};
99100

100101
export const getValidatedFromError = (error: unknown | undefined) => {

0 commit comments

Comments
 (0)