Skip to content
This repository has been archived by the owner on Feb 23, 2024. It is now read-only.

Commit

Permalink
Validate state on options change (#4761)
Browse files Browse the repository at this point in the history
  • Loading branch information
mikejolley authored Sep 21, 2021
1 parent 70dab7c commit b326db2
Showing 1 changed file with 43 additions and 16 deletions.
59 changes: 43 additions & 16 deletions assets/js/base/components/state-input/state-input.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
*/
import { __ } from '@wordpress/i18n';
import { decodeEntities } from '@wordpress/html-entities';
import { useCallback, useMemo } from '@wordpress/element';
import { useCallback, useMemo, useEffect, useRef } from '@wordpress/element';
import classnames from 'classnames';

/**
Expand All @@ -14,6 +14,18 @@ import Combobox from '../combobox';
import './style.scss';
import type { StateInputWithStatesProps } from './StateInputProps';

const optionMatcher = (
value: string,
options: { label: string; value: string }[]
): string => {
const foundOption = options.find(
( option ) =>
option.label.toLocaleUpperCase() === value.toLocaleUpperCase() ||
option.value.toLocaleUpperCase() === value.toLocaleUpperCase()
);
return foundOption ? foundOption.value : '';
};

const StateInput = ( {
className,
id,
Expand All @@ -39,27 +51,41 @@ const StateInput = ( {

/**
* Handles state selection onChange events. Finds a matching state by key or value.
*
* @param {Object} event event data.
*/
const onChangeState = useCallback(
( stateValue ) => {
if ( options.length > 0 ) {
const foundOption = options.find(
( option ) =>
option.label.toLocaleUpperCase() ===
stateValue.toLocaleUpperCase() ||
option.value.toLocaleUpperCase() ===
stateValue.toLocaleUpperCase()
);
onChange( foundOption ? foundOption.value : '' );
return;
}
onChange( stateValue );
( stateValue: string ) => {
onChange(
options.length > 0
? optionMatcher( stateValue, options )
: stateValue
);
},
[ onChange, options ]
);

/**
* Track value changes.
*/
const valueRef = useRef< string >( value );

useEffect( () => {
if ( valueRef.current !== value ) {
valueRef.current = value;
}
}, [ value ] );

/**
* If given a list of options, ensure the value matches those options or trigger change.
*/
useEffect( () => {
if ( options.length > 0 && valueRef.current ) {
const match = optionMatcher( valueRef.current, options );
if ( match !== valueRef.current ) {
onChangeState( match );
}
}
}, [ options, onChangeState ] );

if ( options.length > 0 ) {
return (
<>
Expand Down Expand Up @@ -102,6 +128,7 @@ const StateInput = ( {
</>
);
}

return (
<ValidatedTextInput
className={ className }
Expand Down

0 comments on commit b326db2

Please sign in to comment.