React AutoComplete Component Customization to allow characters input in between tags

112 views Asked by At

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;

0

There are 0 answers