From d743f1e74c30e7b9f73646cc71165d04ffce3c06 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Mon, 1 Feb 2021 18:26:30 +0100 Subject: [PATCH 1/3] added callback for listening to field onerror events --- .../forms/hook_form_lib/components/use_field.tsx | 4 +++- .../static/forms/hook_form_lib/hooks/use_field.ts | 12 +++++++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx index 94c2bc42d28558..cc79ed24b5d0cb 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.tsx @@ -20,6 +20,7 @@ export interface Props { componentProps?: Record; readDefaultValueOnForm?: boolean; onChange?: (value: I) => void; + onError?: (errors: string[] | null) => void; children?: (field: FieldHook) => JSX.Element | null; [key: string]: any; } @@ -33,6 +34,7 @@ function UseFieldComp(props: Props(props: Props(form, path, fieldConfig, onChange); + const field = useField(form, path, fieldConfig, onChange, onError); // Children prevails over anything else provided. if (children) { diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts index c396f223e97fde..db7b0b2820a47d 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/hooks/use_field.ts @@ -27,7 +27,8 @@ export const useField = ( form: FormHook, path: string, config: FieldConfig & InternalFieldConfig = {}, - valueChangeListener?: (value: I) => void + valueChangeListener?: (value: I) => void, + errorChangeListener?: (errors: string[] | null) => void ) => { const { type = FIELD_TYPES.TEXT, @@ -596,6 +597,15 @@ export const useField = ( }; }, [onValueChange]); + useEffect(() => { + if (!isMounted.current) { + return; + } + if (errorChangeListener) { + errorChangeListener(errors.length ? errors.map((error) => error.message) : null); + } + }, [errors, errorChangeListener]); + useEffect(() => { isMounted.current = true; From 898f9cfbbb74c1e20bb6ddc6562f120a86aaf3c5 Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 2 Feb 2021 12:48:31 +0100 Subject: [PATCH 2/3] added onError component integration test --- .../components/use_field.test.tsx | 66 +++++++++++++++++++ 1 file changed, 66 insertions(+) diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx index 36841f8b1d521e..21aef047b6b2a8 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx @@ -287,4 +287,70 @@ describe('', () => { expect(formHook?.getFormData()).toEqual({ name: 'myName' }); }); }); + + describe('change handlers', () => { + interface MyForm { + name: string; + } + + const onError = jest.fn(); + let formHook: FormHook | null = null; + + beforeEach(() => { + jest.resetAllMocks(); + formHook = null; + }); + + const onFormHook = (_form: FormHook) => { + formHook = _form; + }; + + const getTestComp = (fieldConfig: FieldConfig) => { + const TestComp = ({ onForm }: { onForm: (form: FormHook) => void }) => { + const { form } = useForm(); + + useEffect(() => { + onForm(form); + }, [onForm, form]); + + return ( +
+ + + ); + }; + return TestComp; + }; + + const setup = (fieldConfig: FieldConfig) => { + return registerTestBed(getTestComp(fieldConfig), { + memoryRouter: { wrapComponent: false }, + defaultProps: { onForm: onFormHook }, + })() as TestBed; + }; + + it('calls onError when validation state changes', async () => { + const { + form: { setInputValue }, + } = setup({ + validations: [ + { + validator: ({ value }) => (value === '1' ? undefined : { message: 'oops!' }), + }, + ], + }); + + expect(onError).toBeCalledTimes(0); + await act(async () => { + setInputValue('myField', '0'); + }); + expect(onError).toBeCalledTimes(1); + expect(onError).toBeCalledWith(['oops!']); + await act(async () => { + setInputValue('myField', '1'); + }); + expect(onError).toBeCalledTimes(2); + expect(onError).toBeCalledWith(null); + }); + }); }); From 294dab625393c3598aa2285dea498bd38d5fb12f Mon Sep 17 00:00:00 2001 From: Jean-Louis Leysens Date: Tue, 2 Feb 2021 13:34:36 +0100 Subject: [PATCH 3/3] address tslint issues --- .../hook_form_lib/components/use_field.test.tsx | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx index 21aef047b6b2a8..4945b7a059e8c0 100644 --- a/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx +++ b/src/plugins/es_ui_shared/static/forms/hook_form_lib/components/use_field.test.tsx @@ -289,30 +289,16 @@ describe('', () => { }); describe('change handlers', () => { - interface MyForm { - name: string; - } - const onError = jest.fn(); - let formHook: FormHook | null = null; beforeEach(() => { jest.resetAllMocks(); - formHook = null; }); - const onFormHook = (_form: FormHook) => { - formHook = _form; - }; - const getTestComp = (fieldConfig: FieldConfig) => { - const TestComp = ({ onForm }: { onForm: (form: FormHook) => void }) => { + const TestComp = () => { const { form } = useForm(); - useEffect(() => { - onForm(form); - }, [onForm, form]); - return (
@@ -325,7 +311,6 @@ describe('', () => { const setup = (fieldConfig: FieldConfig) => { return registerTestBed(getTestComp(fieldConfig), { memoryRouter: { wrapComponent: false }, - defaultProps: { onForm: onFormHook }, })() as TestBed; };