diff --git a/src/CONST.ts b/src/CONST.ts index 9ce1152d5dcb..491136863f6c 100755 --- a/src/CONST.ts +++ b/src/CONST.ts @@ -2736,6 +2736,12 @@ const CONST = { }, MISSING_TRANSLATION: 'MISSING TRANSLATION', + SEARCH_MAX_LENGTH: 500, + + /** + * The count of characters we'll allow the user to type after reaching SEARCH_MAX_LENGTH in an input. + */ + ADDITIONAL_ALLOWED_CHARACTERS: 20, } as const; export default CONST; diff --git a/src/components/OptionsSelector/BaseOptionsSelector.js b/src/components/OptionsSelector/BaseOptionsSelector.js index 1d0105394042..64896162fb07 100755 --- a/src/components/OptionsSelector/BaseOptionsSelector.js +++ b/src/components/OptionsSelector/BaseOptionsSelector.js @@ -54,6 +54,7 @@ class BaseOptionsSelector extends Component { this.selectRow = this.selectRow.bind(this); this.selectFocusedOption = this.selectFocusedOption.bind(this); this.addToSelection = this.addToSelection.bind(this); + this.updateSearchValue = this.updateSearchValue.bind(this); this.relatedTarget = null; const allOptions = this.flattenSections(); @@ -63,6 +64,7 @@ class BaseOptionsSelector extends Component { allOptions, focusedIndex, shouldDisableRowSelection: false, + errorMessage: '', }; } @@ -167,6 +169,14 @@ class BaseOptionsSelector extends Component { return defaultIndex; } + updateSearchValue(value) { + this.setState({ + errorMessage: value.length > this.props.maxLength ? this.props.translate('common.error.characterLimitExceedCounter', {length: value.length, limit: this.props.maxLength}) : '', + }); + + this.props.onChangeText(value); + } + subscribeToKeyboardShortcut() { const enterConfig = CONST.KEYBOARD_SHORTCUTS.ENTER; this.unsubscribeEnter = KeyboardShortcut.subscribe( @@ -366,10 +376,11 @@ class BaseOptionsSelector extends Component { label={this.props.textInputLabel} accessibilityLabel={this.props.textInputLabel} accessibilityRole={CONST.ACCESSIBILITY_ROLE.TEXT} - onChangeText={this.props.onChangeText} + onChangeText={this.updateSearchValue} + errorText={this.state.errorMessage} onSubmitEditing={this.selectFocusedOption} placeholder={this.props.placeholderText} - maxLength={this.props.maxLength} + maxLength={this.props.maxLength + CONST.ADDITIONAL_ALLOWED_CHARACTERS} keyboardType={this.props.keyboardType} onBlur={(e) => { if (!this.props.shouldFocusOnSelectRow) { @@ -396,7 +407,7 @@ class BaseOptionsSelector extends Component { multipleOptionSelectorButtonText={this.props.multipleOptionSelectorButtonText} onAddToSelection={this.addToSelection} hideSectionHeaders={this.props.hideSectionHeaders} - headerMessage={this.props.headerMessage} + headerMessage={this.state.errorMessage ? '' : this.props.headerMessage} boldStyle={this.props.boldStyle} showTitleTooltip={this.props.showTitleTooltip} isDisabled={this.props.isDisabled} diff --git a/src/components/OptionsSelector/optionsSelectorPropTypes.js b/src/components/OptionsSelector/optionsSelectorPropTypes.js index 8a7158092967..942cf8a9099d 100644 --- a/src/components/OptionsSelector/optionsSelectorPropTypes.js +++ b/src/components/OptionsSelector/optionsSelectorPropTypes.js @@ -1,6 +1,7 @@ import PropTypes from 'prop-types'; import optionPropTypes from '../optionPropTypes'; import styles from '../../styles/styles'; +import CONST from '../../CONST'; const propTypes = { /** Callback to fire when a row is tapped */ @@ -157,7 +158,7 @@ const defaultProps = { isDisabled: false, shouldHaveOptionSeparator: false, initiallyFocusedOptionKey: undefined, - maxLength: undefined, + maxLength: CONST.SEARCH_MAX_LENGTH, shouldShowTextInput: true, onChangeText: () => {}, shouldUseStyleForChildren: true, diff --git a/src/languages/en.ts b/src/languages/en.ts index b4d83ac36217..700ecf334a9b 100755 --- a/src/languages/en.ts +++ b/src/languages/en.ts @@ -193,6 +193,7 @@ export default { phoneNumber: `Please enter a valid phone number, with the country code (e.g. ${CONST.EXAMPLE_PHONE_NUMBER})`, fieldRequired: 'This field is required.', characterLimit: ({limit}: CharacterLimitParams) => `Exceeds the maximum length of ${limit} characters`, + characterLimitExceedCounter: ({length, limit}) => `Character limit exceeded (${length}/${limit})`, dateInvalid: 'Please select a valid date', invalidCharacter: 'Invalid character', enterMerchant: 'Enter a merchant name', diff --git a/src/languages/es.ts b/src/languages/es.ts index 0e87425f3dde..a16411eb6a70 100644 --- a/src/languages/es.ts +++ b/src/languages/es.ts @@ -183,6 +183,7 @@ export default { phoneNumber: `Introduce un teléfono válido, incluyendo el código del país (p. ej. ${CONST.EXAMPLE_PHONE_NUMBER})`, fieldRequired: 'Este campo es obligatorio.', characterLimit: ({limit}: CharacterLimitParams) => `Supera el límite de ${limit} caracteres`, + characterLimitExceedCounter: ({length, limit}) => `Se superó el límite de caracteres (${length}/${limit})`, dateInvalid: 'Por favor, selecciona una fecha válida', invalidCharacter: 'Carácter invalido', enterMerchant: 'Introduce un comerciante',