From 1d081804f744ae7eb057878af0c6cd9c8eb4b76b Mon Sep 17 00:00:00 2001 From: adamviktora Date: Tue, 13 Jun 2023 14:41:21 +0200 Subject: [PATCH 1/7] fix(DatePicker): clear error on date reset --- .../react-core/src/components/DatePicker/DatePicker.tsx | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/packages/react-core/src/components/DatePicker/DatePicker.tsx b/packages/react-core/src/components/DatePicker/DatePicker.tsx index 4ab92e187dc..728aae46391 100644 --- a/packages/react-core/src/components/DatePicker/DatePicker.tsx +++ b/packages/react-core/src/components/DatePicker/DatePicker.tsx @@ -141,10 +141,11 @@ const DatePickerBase = ( }, [valueProp]); React.useEffect(() => { - setPristine(!value); + setPristine(value === ''); const newValueDate = dateParse(value); - if (errorText && isValidDate(newValueDate)) { - setError(newValueDate); + if (errorText) { + isValidDate(newValueDate) && setError(newValueDate); + value === '' && setErrorText(''); } }, [value]); From 11a1a20b74610684922d243b7fb8e89e8fd868b7 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Tue, 13 Jun 2023 14:42:10 +0200 Subject: [PATCH 2/7] feat(DatePicker): add clear date example to controlled DatePicker --- .../DatePicker/examples/DatePickerControlled.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerControlled.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerControlled.tsx index a305b70330f..a4297e9265e 100644 --- a/packages/react-core/src/components/DatePicker/examples/DatePickerControlled.tsx +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerControlled.tsx @@ -1,5 +1,5 @@ import React from 'react'; -import { Button, DatePicker } from '@patternfly/react-core'; +import { Button, DatePicker, Flex, FlexItem } from '@patternfly/react-core'; export const DatePickerControlled: React.FunctionComponent = () => { const initialValue = '2020-03-17'; @@ -9,7 +9,14 @@ export const DatePickerControlled: React.FunctionComponent = () => { setValue(value)} />

- + + + + + + + + ); }; From 6c1bb48c5c385c2a77d7a0c78080660a5e1b737e Mon Sep 17 00:00:00 2001 From: adamviktora Date: Tue, 13 Jun 2023 15:23:30 +0200 Subject: [PATCH 3/7] test(DatePicker): add integration test for clear date --- .../cypress/integration/datepicker.spec.ts | 9 +++++++++ .../components/demos/DatePickerDemo/DatePickerDemo.tsx | 6 ++++++ 2 files changed, 15 insertions(+) diff --git a/packages/react-integration/cypress/integration/datepicker.spec.ts b/packages/react-integration/cypress/integration/datepicker.spec.ts index 53cecdfb50b..51e5f959866 100644 --- a/packages/react-integration/cypress/integration/datepicker.spec.ts +++ b/packages/react-integration/cypress/integration/datepicker.spec.ts @@ -18,6 +18,15 @@ xit('Verify validation error can be cleared from outside', () => { cy.get('div.pf-m-error').should('not.exist'); }); +it('Verify error can be cleared when resetting the date from outside', () => { + cy.get('#date-picker-clear .pf-v5-c-form-control input').click(); + cy.focused().clear().type('something invalid'); + cy.focused().blur(); + cy.get('div.pf-m-error').should('exist'); + cy.get('button').contains('Clear date').click(); + cy.get('div.pf-m-error').should('not.exist'); +}); + it('Verify calendar state can be controlled', () => { cy.get('#date-picker-controlled .pf-v5-c-popover').should('not.exist'); cy.get('button').contains('Toggle').click(); diff --git a/packages/react-integration/demo-app-ts/src/components/demos/DatePickerDemo/DatePickerDemo.tsx b/packages/react-integration/demo-app-ts/src/components/demos/DatePickerDemo/DatePickerDemo.tsx index b61f84e7898..c7eaf5a2966 100644 --- a/packages/react-integration/demo-app-ts/src/components/demos/DatePickerDemo/DatePickerDemo.tsx +++ b/packages/react-integration/demo-app-ts/src/components/demos/DatePickerDemo/DatePickerDemo.tsx @@ -14,6 +14,12 @@ export const DatePickerDemo = () => { return ( <> +
+ +
+ +
+
setValue(value)} validators={[rangeValidator]} />
From 12f946bb56d9617cced794007e31c5f7b3ecb4c4 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Mon, 31 Jul 2023 13:00:22 +0200 Subject: [PATCH 4/7] feat(DatePicker): update clear date logic based on #9373 --- .../react-core/src/components/DatePicker/DatePicker.tsx | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/packages/react-core/src/components/DatePicker/DatePicker.tsx b/packages/react-core/src/components/DatePicker/DatePicker.tsx index 728aae46391..420e1210d02 100644 --- a/packages/react-core/src/components/DatePicker/DatePicker.tsx +++ b/packages/react-core/src/components/DatePicker/DatePicker.tsx @@ -50,6 +50,8 @@ export interface DatePickerProps isDisabled?: boolean; /** Error message to display when the text input contains a non-empty value in an invalid format. */ invalidFormatText?: string; + /** Error message to display when the text input is empty and the isRequired prop is also passed in. */ + emptyDateText?: string; /** Callback called every time the text input loses focus. */ onBlur?: (event: any, value: string, date?: Date) => void; /** Callback called every time the text input value changes. */ @@ -98,6 +100,7 @@ const DatePickerBase = ( dateFormat = yyyyMMddFormat, dateParse = (val: string) => val.split('-').length === 3 && new Date(`${val}T00:00:00`), isDisabled = false, + isRequired = false, placeholder = 'YYYY-MM-DD', value: valueProp = '', 'aria-label': ariaLabel = 'Date picker', @@ -145,7 +148,9 @@ const DatePickerBase = ( const newValueDate = dateParse(value); if (errorText) { isValidDate(newValueDate) && setError(newValueDate); - value === '' && setErrorText(''); + if (value === '') { + isRequired ? setErrorText(emptyDateText) : setErrorText(''); + } } }, [value]); From 0a971ab47a5f107bdad4934a333ce0868162c991 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Fri, 18 Aug 2023 12:12:47 +0200 Subject: [PATCH 5/7] fix(DatePicker): hide error when date cleared and not required + show error when cleared and required --- .../src/components/DatePicker/DatePicker.tsx | 11 +++++--- .../DatePicker/examples/DatePicker.md | 6 +++++ .../examples/DatePickerControlledRequired.tsx | 26 +++++++++++++++++++ 3 files changed, 39 insertions(+), 4 deletions(-) create mode 100644 packages/react-core/src/components/DatePicker/examples/DatePickerControlledRequired.tsx diff --git a/packages/react-core/src/components/DatePicker/DatePicker.tsx b/packages/react-core/src/components/DatePicker/DatePicker.tsx index 420e1210d02..89c6703ae46 100644 --- a/packages/react-core/src/components/DatePicker/DatePicker.tsx +++ b/packages/react-core/src/components/DatePicker/DatePicker.tsx @@ -100,7 +100,6 @@ const DatePickerBase = ( dateFormat = yyyyMMddFormat, dateParse = (val: string) => val.split('-').length === 3 && new Date(`${val}T00:00:00`), isDisabled = false, - isRequired = false, placeholder = 'YYYY-MM-DD', value: valueProp = '', 'aria-label': ariaLabel = 'Date picker', @@ -131,11 +130,13 @@ const DatePickerBase = ( const [popoverOpen, setPopoverOpen] = React.useState(false); const [selectOpen, setSelectOpen] = React.useState(false); const [pristine, setPristine] = React.useState(true); + const [textInputFocused, setTextInputFocused] = React.useState(false); const widthChars = React.useMemo(() => Math.max(dateFormat(new Date()).length, placeholder.length), [dateFormat]); const style = { '--pf-v5-c-date-picker__input--c-form-control--width-chars': widthChars, ...styleProps }; const buttonRef = React.useRef(); const datePickerWrapperRef = React.useRef(); const triggerRef = React.useRef(); + const dateIsRequired = requiredDateOptions?.isRequired || false; const emptyDateText = requiredDateOptions?.emptyDateText || 'Date cannot be blank'; React.useEffect(() => { @@ -148,9 +149,9 @@ const DatePickerBase = ( const newValueDate = dateParse(value); if (errorText) { isValidDate(newValueDate) && setError(newValueDate); - if (value === '') { - isRequired ? setErrorText(emptyDateText) : setErrorText(''); - } + } + if (value === '' && !pristine && !textInputFocused) { + dateIsRequired ? setErrorText(emptyDateText) : setErrorText(''); } }, [value]); @@ -171,6 +172,7 @@ const DatePickerBase = ( }; const onInputBlur = (event: any) => { + setTextInputFocused(false); const newValueDate = dateParse(value); const dateIsValid = isValidDate(newValueDate); const onBlurDateArg = dateIsValid ? new Date(newValueDate) : undefined; @@ -288,6 +290,7 @@ const DatePickerBase = ( value={value} onChange={onTextInput} onBlur={onInputBlur} + onFocus={() => setTextInputFocused(true)} onKeyPress={onKeyPress} {...inputProps} /> diff --git a/packages/react-core/src/components/DatePicker/examples/DatePicker.md b/packages/react-core/src/components/DatePicker/examples/DatePicker.md index 4d5959b29b0..0456a0bfd14 100644 --- a/packages/react-core/src/components/DatePicker/examples/DatePicker.md +++ b/packages/react-core/src/components/DatePicker/examples/DatePicker.md @@ -56,6 +56,12 @@ The error message can be customized via the `requiredDateOptions.emptyDateText` ``` +### Controlled required + +```ts file="./DatePickerControlledRequired.tsx" + +``` + ### Controlling the date picker calendar state ```ts file="./DatePickerControlledCalendar.tsx" diff --git a/packages/react-core/src/components/DatePicker/examples/DatePickerControlledRequired.tsx b/packages/react-core/src/components/DatePicker/examples/DatePickerControlledRequired.tsx new file mode 100644 index 00000000000..4ba5bf302da --- /dev/null +++ b/packages/react-core/src/components/DatePicker/examples/DatePickerControlledRequired.tsx @@ -0,0 +1,26 @@ +import React from 'react'; +import { Button, DatePicker, Flex, FlexItem } from '@patternfly/react-core'; + +export const DatePickerControlled: React.FunctionComponent = () => { + const initialValue = '2020-03-17'; + const [value, setValue] = React.useState(initialValue); + return ( + + setValue(value)} + /> +
+
+ + + + + + + + +
+ ); +}; From e1fe6a5634277a8e2763b4e5f9d5ae75e57cf93f Mon Sep 17 00:00:00 2001 From: adamviktora Date: Fri, 18 Aug 2023 12:16:43 +0200 Subject: [PATCH 6/7] refactor(DatePicker) --- .../react-core/src/components/DatePicker/DatePicker.tsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/packages/react-core/src/components/DatePicker/DatePicker.tsx b/packages/react-core/src/components/DatePicker/DatePicker.tsx index 89c6703ae46..7700160dd49 100644 --- a/packages/react-core/src/components/DatePicker/DatePicker.tsx +++ b/packages/react-core/src/components/DatePicker/DatePicker.tsx @@ -145,10 +145,10 @@ const DatePickerBase = ( }, [valueProp]); React.useEffect(() => { - setPristine(value === ''); + setPristine(!value); const newValueDate = dateParse(value); - if (errorText) { - isValidDate(newValueDate) && setError(newValueDate); + if (errorText && isValidDate(newValueDate)) { + setError(newValueDate); } if (value === '' && !pristine && !textInputFocused) { dateIsRequired ? setErrorText(emptyDateText) : setErrorText(''); From 5c4b317dbc2208f3c9dce0e417c3c344f870c578 Mon Sep 17 00:00:00 2001 From: adamviktora Date: Thu, 24 Aug 2023 13:31:41 +0200 Subject: [PATCH 7/7] fix(DatePicker): prop removal --- packages/react-core/src/components/DatePicker/DatePicker.tsx | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/react-core/src/components/DatePicker/DatePicker.tsx b/packages/react-core/src/components/DatePicker/DatePicker.tsx index 7700160dd49..d360673f945 100644 --- a/packages/react-core/src/components/DatePicker/DatePicker.tsx +++ b/packages/react-core/src/components/DatePicker/DatePicker.tsx @@ -50,8 +50,6 @@ export interface DatePickerProps isDisabled?: boolean; /** Error message to display when the text input contains a non-empty value in an invalid format. */ invalidFormatText?: string; - /** Error message to display when the text input is empty and the isRequired prop is also passed in. */ - emptyDateText?: string; /** Callback called every time the text input loses focus. */ onBlur?: (event: any, value: string, date?: Date) => void; /** Callback called every time the text input value changes. */