I am trying to create a react component with Custom AutoComplete functionality. My current logic is working fine on searching the input and then creating tags inside input field on selecting the suggested answer. But i want to customize it so that if i enter a character dint got any suggestion in search filter then it should consider it as text field input and when i enter the next character it start searching on the basis of that last particular character. E.g I enter "a" and it shows apple i selected it, then i enter "+" it shows no suggestion, after this if i enter "b" then it should show ball in the suggestions list to select and "+" should remain there in the Text filed, in between both tags.
Here is the code which i did so far to achieve the mentioned requirements.
import React, { useState } from "react";
import Autocomplete from "@mui/material/Autocomplete";
import TextField from "@mui/material/TextField";
const MultiAutocomplete = () => {
const [value, setValue] = useState([]);
const [inputValue, setInputValue] = useState("");
const [searchIndex, setSearchIndex] = useState(0);
const names = ["apple", "banana", "cherry", "date", "fig"];
// Handle when an option is selected (tag created)
const handleOptionSelect = (event, newValue) => {
debugger
console.log("value 1= ", newValue);
setValue(newValue);
setSearchIndex(0); // Reset the search index when an option is selected
};
// Handle when text is typed into the input
const handleInputChange = (event, newInputValue) => {
debugger;
console.log("value = ", newInputValue);
setInputValue(newInputValue);
setSearchIndex(0); // Reset the search index when the input changes
};
// Find the next available suggestion
const findNextSuggestion = () => {
debugger
console.log("value 3= ");
let currentIndex = searchIndex;
const lastInputPart = inputValue.toLowerCase();
while (currentIndex < lastInputPart.length) {
const suggestion = names[currentIndex].toLowerCase();
if (suggestion.startsWith(lastInputPart)) {
setSearchIndex(currentIndex + 1);
return names[currentIndex];
}
currentIndex++;
}
setSearchIndex(0); // Reset the search index if no suggestion is found
return "";
};
// Handle adding a tag based on the current input
const handleAddTag = () => {
debugger
console.log("value 4");
const nextSuggestion = findNextSuggestion();
if (nextSuggestion === inputValue) {
// Add the tag only if the suggestion matches the input
setValue([...value, inputValue]);
setInputValue(""); // Clear the input field
} else {
// Skip the character against which no suggestion is found
setInputValue(nextSuggestion);
}
};
return (
<Autocomplete
sx={{ m: 1, width: 500 }}
multiple
id="tags-standard"
options={names}
value={value}
onChange={handleOptionSelect}
inputValue={inputValue}
onInputChange={handleInputChange}
disableCloseOnSelect
renderOption={(props, option, { selected }) => (
<li {...props}>{option}</li>
)}
renderInput={(params) => (
<TextField
{...params}
variant="outlined"
label="Multiple Autocomplete"
placeholder="Type to add tags"
onKeyDown={(e) => {
if (e.key === "Enter") {
handleAddTag();
}
}}
/>
)}
isOptionEqualToValue={(option, value) => option === value}
freeSolo={true}
/>
);
};
export default MultiAutocomplete;