Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

AsyncCreatableSelect not allowing to enter more than character to search or create #5922

Open
Kranthi32 opened this issue Jun 18, 2024 · 0 comments
Labels
issue/bug-unconfirmed Issues that describe a bug that hasn't been confirmed by a maintainer yet

Comments

@Kranthi32
Copy link

this is my code below mentioned.AsyncCreatableSelect not allowing to enter more than character to search or create please suggest

import React, { useState, useEffect, useCallback } from 'react';
import Select, { StylesConfig, ActionMeta, components } from 'react-select';
import AsyncSelect from 'react-select/async';
import makeAnimated from 'react-select/animated';
import CreatableSelect from 'react-select/creatable';
import AsyncCreatableSelect from 'react-select/async-creatable';
import ReactTooltip, { Tooltip } from "react-tooltip";
import { DropdownProps, Option } from '@/Interface/Dropdown';
import dropdownData from '@/Mockup/Dropdown.json';
import useFetch from '@/Hooks/useFetch';
import { encrypt, decrypt } from '@/Utils/CryptoUtils';

const { alignmentClassMap }: { alignmentClassMap: Record<string, string> } = dropdownData;

const getSelectContainer = (options: { tooltipText: string; tooltipId: string }) => (props: any) => (
<components.SelectContainer
{...props}
innerProps={{
...props.innerProps,
'data-tip': options.tooltipText,
'data-for': options.tooltipId,
}}
/>
);

const Dropdown: React.FC = ({
Label,
Name,
Class,
Color = '#000000',
Placeholder,
Disabled,
ReadOnly = false,
Width = 'w-full',
Alignment = 'left',
Required = false,
Options,
Value: initialValue = null,
Reset = false,
IsSearchable = false,
Rtl = false,
LabelClass,
LabelColor = "#000000",
Icon,
IsMultiSelect = false,
EnableTooltip = true,
TooltipText = "dsagfsdg",
ValidationMessage,
onChange,
OptionsUrl = null,
Async = false,
AsyncOptionsUrl = null,
Algorithm = 'AES',
Encryption = true,
Decryption = true,
BlockHelper,
CreateNew = false,

}) => {

const [selectedValue, setSelectedValue] = useState<Option | Option[] | null>(initialValue);
const [optionsToUse, setOptionsToUse] = useState<Option[]>(Options);
const { data, isLoading, error } = useFetch<Option[]>(OptionsUrl || '');
const [inputValue, setInputValue] = useState('');
const [inputValueState, setInputValueState] = useState('');

useEffect(() => {
if (OptionsUrl) {
if (data) {
setOptionsToUse(data);
}
} else {
setOptionsToUse(Options);
}
}, [Options, OptionsUrl, data]);

// load options using API call
const loadOptionsPromise = async (inputValue: string): Promise<Option[]> => {
try {
const response = await fetch(${AsyncOptionsUrl}?search=${inputValue});
const json = await response.json();
return json;
} catch (error) {
console.error('Error loading options:', error);
return [];
}
};

const handleOnInputChange = (inputValue: string) => {
let result = inputValue.substring(0,3);
const forbiddenCharacters = /[^a-zA-Z0-9.\-_ ]/g;
if(result.match(forbiddenCharacters)){
result = result.replace(forbiddenCharacters, '');
}
setInputValueState(result);
}

const createOption = (label: string) => ({
label,
value: label.toLowerCase().replace(/\W/g, ''),
});

const handleCreate = (inputValue: string) => {
const newOption = createOption(inputValue);
setOptionsToUse((prev) => {
const updatedOptions = [...prev, newOption];
console.log('Updated optionsToUse:', updatedOptions);
return updatedOptions;
});
console.info('optionstoUse',optionsToUse)
if (IsMultiSelect && Array.isArray(selectedValue)) {
const newSelectedValues = [...selectedValue, newOption];
setSelectedValue(newSelectedValues);
} else {
setSelectedValue(newOption);
}

setInputValue('');

};

const customStyles: StylesConfig<Option, boolean> = {
control: (provided, state) => ({
...provided,
width: '100%',
color: Color,
direction: Rtl ? 'rtl' : 'ltr',
borderColor: state.isFocused
? (Required && (!selectedValue || (Array.isArray(selectedValue) && selectedValue.length === 0)))
? 'red' : provided.borderColor
: provided.borderColor,
'&:hover': {
borderColor: state.isFocused
? (Required && (!selectedValue || (Array.isArray(selectedValue) && selectedValue.length === 0)))
? 'red' : provided.borderColor
: provided.borderColor,
},
}),
placeholder: (provided) => ({
...provided,
color: Color,
}),
singleValue: (provided) => ({
...provided,
color: Color,
}),
multiValue: (provided) => ({
...provided,
}),
multiValueLabel: (provided) => ({
...provided,
color: Color,
}),
multiValueRemove: (provided) => ({
...provided,
color: Color,
}),
input: (provided) => ({
...provided,
color: Color,
}),
};

const animatedComponents = makeAnimated();

// Handle change in selected value(s)
const handleChange = (option: any) => {
setSelectedValue(option);

if (onChange) {
  onChange(Name, option);
}

};

const handleInputChange = (newValue: string) => {
setInputValue(newValue);
return newValue;
};

useEffect(() => {
if (Encryption && selectedValue) {
const encryptedValue = Array.isArray(selectedValue)
? selectedValue.map(val => encrypt(val.value, Algorithm)).join(',')
: encrypt(selectedValue.value, Algorithm);
const selectElement = document.querySelector([name="${Name}"]);
if (selectElement) {
selectElement.setAttribute('data-encrypted-value', encryptedValue);
}
}
}, [selectedValue, Encryption, Algorithm, Name]);

if (isLoading) return

Loading...

;
if (error) return
Error: {error.message}
;

return (
<div className={relative }>
{/* Label */}
{Label && (
<label className={${LabelClass}} style={{ color: LabelColor }}>
{Label}

)}

  {/* Dropdown */}
  <div className={`relative flex items-center ${!Rtl ? alignmentClassMap[Alignment] : ''}`}>
    {Async ?
          CreateNew ? // Async - true, create New Option - true
            <AsyncCreatableSelect
              name={Name}
              classNamePrefix="react-select"
              placeholder={Placeholder}
              isDisabled={Disabled || ReadOnly}
              isMulti={IsMultiSelect}
              isClearable={Reset}
              loadOptions={loadOptionsPromise}
              defaultOptions={optionsToUse}
              options={optionsToUse}
              defaultValue={initialValue}
              value={selectedValue}
              onChange={(option: any) => handleChange(option)}
              allowCreateWhileLoading={true}
              isSearchable={IsSearchable}
              onInputChange={handleInputChange}
              inputValue={inputValue}
              noOptionsMessage={() => (isLoading ? 'Loading...' : 'No options')}
              styles={customStyles}
              components={{
                SelectContainer: getSelectContainer({
                  tooltipText: TooltipText,
                  tooltipId: 'currency-tooltip',
                }),
              }}
              data-tooltip-id={EnableTooltip ? "currency-tooltip" : undefined}
              data-tooltip-content={EnableTooltip ? TooltipText : ValidationMessage}
              className={`${Class} ${Width}  border ${Required && (!selectedValue || (Array.isArray(selectedValue) && selectedValue.length === 0)) ? 'border-red-500' : 'border-gray-300'}`}
              onCreateOption={handleCreate}
            />
            : 
            <AsyncSelect // Async - true, create New Option - false
              name={Name}
              classNamePrefix="react-select"
              placeholder={Placeholder}
              isDisabled={Disabled || ReadOnly}
              isMulti={IsMultiSelect}
              isClearable={Reset}
              loadOptions={loadOptionsPromise}
              defaultOptions={optionsToUse}
              options={optionsToUse}
              defaultValue={initialValue}
              value={selectedValue}
              onChange={(option) => handleChange(option)}
              isSearchable={IsSearchable}
              onInputChange={handleInputChange}
              inputValue={inputValue}
              noOptionsMessage={() => (isLoading ? 'Loading...' : 'No options')}
              styles={customStyles}
              components={{
                SelectContainer: getSelectContainer({
                  tooltipText: TooltipText,
                  tooltipId: 'currency-tooltip',
                }),
              }}
              data-tooltip-id={EnableTooltip ? "currency-tooltip" : undefined}
              data-tooltip-content={EnableTooltip ? TooltipText : ValidationMessage}
              className={`${Class} ${Width}  border ${Required && (!selectedValue || (Array.isArray(selectedValue) && selectedValue.length === 0)) ? 'border-red-500' : 'border-gray-300'}`}
            />
      :  //Normal Select Async False
        CreateNew ?  //Async false create New

        <CreatableSelect
          name={Name}
          classNamePrefix="react-select"
          placeholder={Placeholder}
          isDisabled={Disabled || ReadOnly}
          isMulti={IsMultiSelect}
          isClearable={Reset}
          options={optionsToUse}
          defaultValue={initialValue}
          value={selectedValue}
          onChange={(option) => handleChange(option)}
          isSearchable={IsSearchable}
          styles={customStyles}
          components={{
            SelectContainer: getSelectContainer({
              tooltipText: TooltipText,
              tooltipId: 'currency-tooltip',
            }),
          }}
          data-tooltip-id={EnableTooltip ? "currency-tooltip" : undefined}
          data-tooltip-content={EnableTooltip ? TooltipText : ValidationMessage}
          className={`${Class} ${Width}  border ${Required && (!selectedValue || (Array.isArray(selectedValue) && selectedValue.length === 0)) ? 'border-red-500' : 'border-gray-300'}`}
          onCreateOption={handleCreate}
        />

        :  //Async false create New false
        <Select
          name={Name}
          classNamePrefix="react-select"
          placeholder={Placeholder}
          isDisabled={Disabled || ReadOnly}
          isMulti={IsMultiSelect}
          isClearable={Reset}
          options={optionsToUse}
          defaultValue={initialValue}
          value={selectedValue}
          onChange={(option) => handleChange(option)}
          isSearchable={IsSearchable}
          styles={customStyles}
          components={{
            SelectContainer: getSelectContainer({
              tooltipText: TooltipText,
              tooltipId: 'currency-tooltip',
            }),
          }}
          data-tooltip-id={EnableTooltip ? "currency-tooltip" : undefined}
          data-tooltip-content={EnableTooltip ? TooltipText : ValidationMessage}
          className={`${Class} ${Width}  border ${Required && (!selectedValue || (Array.isArray(selectedValue) && selectedValue.length === 0)) ? 'border-red-500' : 'border-gray-300'}`}
        />
    }
  </div>

  {/* Tooltip */}
  {EnableTooltip && (
    <Tooltip variant="info" place="bottom" id='currency-tooltip' />
  )}

   {/* Block Helper */}
  {BlockHelper  && (
    <p className="mt-2 text-sm text-gray-500">  {(BlockHelper || '')} </p>
  )}

  {/* Validation Message */}
  {Required && (!selectedValue || (Array.isArray(selectedValue) && selectedValue.length === 0)) && ValidationMessage && (
    <span className="validation-message">
      {ValidationMessage}
    </span>
  )}
</div>

);
};

export default Dropdown;

@Kranthi32 Kranthi32 added the issue/bug-unconfirmed Issues that describe a bug that hasn't been confirmed by a maintainer yet label Jun 18, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
issue/bug-unconfirmed Issues that describe a bug that hasn't been confirmed by a maintainer yet
Projects
None yet
Development

No branches or pull requests

1 participant