Skip to content

Commit

Permalink
Trigger validation on change (woocommerce#5373)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikejolley authored and jonny-bull committed Dec 14, 2021
1 parent dfa371c commit 0a40a02
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 25 deletions.
3 changes: 3 additions & 0 deletions assets/js/base/components/button/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,9 @@ interface ButtonProps extends WPButton.ButtonProps {
className?: string;
showSpinner?: boolean;
children?: ReactNode;
disabled?: boolean;
onClick?: ( e: React.MouseEvent< HTMLButtonElement, MouseEvent > ) => void;
type?: 'input' | 'submit';
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,28 +57,27 @@ const validateShippingCountry = (
};

interface AddressFormProps {
id: string;
// Id for component.
id?: string;
// Unique id for form.
instanceId: string;
// Array of fields in form.
fields: ( keyof AddressFields )[];
fieldConfig: Record< keyof AddressFields, Partial< AddressField > >;
// Field configuration for fields in form.
fieldConfig?: Record< keyof AddressFields, Partial< AddressField > >;
// Function to all for an form onChange event.
onChange: ( newValue: EnteredAddress ) => void;
type: AddressType;
// Type of form.
type?: AddressType;
// Values for fields.
values: EnteredAddress;
}

/**
* Checkout address form.
*
* @param {Object} props Incoming props for component.
* @param {string} props.id Id for component.
* @param {Array} props.fields Array of fields in form.
* @param {Object} props.fieldConfig Field configuration for fields in form.
* @param {string} props.instanceId Unique id for form.
* @param {function(any):any} props.onChange Function to all for an form onChange event.
* @param {string} props.type Type of form.
* @param {Object} props.values Values for fields.
*/
const AddressForm = ( {
id,
id = '',
fields = ( Object.keys(
defaultAddressFields
) as unknown ) as ( keyof AddressFields )[],
Expand Down
27 changes: 15 additions & 12 deletions assets/js/base/components/text-input/validated-text-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ import classnames from 'classnames';
import {
ValidationInputError,
useValidationContext,
useCheckoutContext,
} from '@woocommerce/base-context';
import { withInstanceId } from '@wordpress/compose';
import { isString } from '@woocommerce/types';
Expand Down Expand Up @@ -64,9 +63,6 @@ const ValidatedTextInput = ( {
clearValidationError,
getValidationErrorId,
} = useValidationContext();

const { isBeforeProcessing } = useCheckoutContext();

const textInputId =
typeof id !== 'undefined' ? id : 'textinput-' + instanceId;
const errorIdString = errorId !== undefined ? errorId : textInputId;
Expand Down Expand Up @@ -99,6 +95,18 @@ const ValidatedTextInput = ( {
[ clearValidationError, errorIdString, setValidationErrors ]
);

/**
* Runs validation on change if the current element is not in focus. This is because autofilled elements do not
* trigger the blur() event.
*/
const maybeValidateOnChange = useCallback( () => {
if (
inputRef.current?.ownerDocument.activeElement !== inputRef.current
) {
validateInput( true );
}
}, [ validateInput ] );

useEffect( () => {
if ( isPristine ) {
if ( focusOnMount ) {
Expand All @@ -117,14 +125,6 @@ const ValidatedTextInput = ( {
}
}, [ isPristine, setIsPristine, validateOnMount, validateInput ] );

/**
* @todo Remove extra validation call after refactoring the validation system.
*/
useEffect( () => {
if ( isBeforeProcessing ) {
validateInput();
}
}, [ isBeforeProcessing, validateInput ] );
// Remove validation errors when unmounted.
useEffect( () => {
return () => {
Expand All @@ -137,9 +137,11 @@ const ValidatedTextInput = ( {
message?: string;
hidden?: boolean;
};

if ( isString( passedErrorMessage ) && passedErrorMessage !== '' ) {
errorMessage.message = passedErrorMessage;
}

const hasError = errorMessage.message && ! errorMessage.hidden;
const describedBy =
showError && hasError && getValidationErrorId( errorIdString )
Expand Down Expand Up @@ -168,6 +170,7 @@ const ValidatedTextInput = ( {
onChange={ ( val ) => {
hideValidationError( errorIdString );
onChange( val );
maybeValidateOnChange();
} }
ariaDescribedBy={ describedBy }
{ ...rest }
Expand Down

0 comments on commit 0a40a02

Please sign in to comment.